[java I/O]在socket传输中,用writeUnshared()写入对象,每次发送的是第一个对象

writeUnshared的API:
Writes an "unshared" object to the ObjectOutputStream. This method is identical to writeObject, except that it always writes the given object as a new, unique object in the stream (as opposed to a back-reference pointing to a previously serialized instance). Specifically:

  • An object written via writeUnshared is always serialized in the same manner as a newly appearing object (an object that has not been written to the stream yet), regardless of whether or not the object has been written previously.

  • If writeObject is used to write an object that has been previously written with writeUnshared, the previous writeUnshared operation is treated as if it were a write of a separate object. In other words, ObjectOutputStream will never generate back-references to object data written by calls to writeUnshared.

之前是用writeObject,不过在流中反复发送第一次发送的对象,调用hashcode()判断了是同一对象,就不再写这个对象到流了。后来查API看到了writeUnshared()方法

通过 writeUnshared 写入的对象总是作为新出现对象(未曾将对象写入流中)被序列化,不管该对象以前是否已经被写入过。
但修改过后,仍未解决~

  • client

        try {
            DatagramSocket socket = new DatagramSocket(clientSocketAddr);
            DataPacketHeader dph = new DataPacketHeader(true,true,1,12);
            DataPacket dp = new DataPacket(dph);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream dos = new ObjectOutputStream(baos);
            int count = 0;
           for(int i = 0;i<3;i++){
               count++;
               dph.setAckNum(count);
               dos.writeUnshared(dph);//here!!!!!
                dos.flush();
               byte buf[] = baos.toByteArray();
               DatagramPacket dpk = new DatagramPacket(buf,buf.length,serverSocketAddr);
               socket.send(dpk);
               //dos.close();
           }
        } catch (SocketException e) {
            e.printStackTrace();
        }
  • server

        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        DatagramSocket socket = null;
        try {
            socket = new DatagramSocket(serverSocketAddr);
            byte recvBuf[] = new byte[1024 * 100];
            DatagramPacket recvDp = new DatagramPacket(recvBuf, recvBuf.length);
            DataPacketHeader dataPacket = null;
            while (true) {
                socket.receive(recvDp);
                bais = new ByteArrayInputStream(recvBuf);
                ois = new ObjectInputStream(bais);
                 dataPacket = (DataPacketHeader) ois.readUnshared();//here!!!!!
                System.out.println(dataPacket.getAckNum()+"|"+dataPacket.getSeqNum());
            }
        }catch(xxx){
           xxx
        }
        ...

所要序列化的对象

package main.common;

import java.io.Serializable;

public class DataPacketHeader implements Serializable {
    private boolean ACK;
    private boolean SYN;
    private int ackNum;
    private int seqNum;
    private int packetLength;

    public DataPacketHeader(boolean ACK, boolean SYN, int ackNum, int seqNum) {
        this.ACK = ACK;
        this.SYN = SYN;
        this.ackNum = ackNum;
        this.seqNum = seqNum;
        //this.packetLength = packetLength;
    }

    public boolean isACK() {
        return ACK;
    }

    public void setACK(boolean ACK) {
        this.ACK = ACK;
    }

    public boolean isSYN() {
        return SYN;
    }

    public void setSYN(boolean SYN) {
        this.SYN = SYN;
    }

    public int getAckNum() {
        return ackNum;
    }

    public void setAckNum(int ackNum) {
        this.ackNum = ackNum;
    }

    public int getSeqNum() {
        return seqNum;
    }

    public void setSeqNum(int seqNum) {
        this.seqNum = seqNum;
    }

    public int getPacketLength() {
        return packetLength;
    }

    public void setPacketLength(int packetLength) {
        this.packetLength = packetLength;
    }
}

结果:
1|12
1|12
1|12
读取到的是同一对象

阅读 2.5k
1 个回答

你可以试下打印每次发送的packet的长度,可以知道每次发送的对象都是逐步增大的,说明bytearray中保存的数组一直在增大,所以,在server端读的第一个对象永远是 1|12.
如果你想实现每次读出来不一样,就只能在for循环中new ByteArrayOutputStream和 ObjectOutputStream

    for (int i = 0; i < 3; i++) {
         count++;
         dph.setAckNum(count);
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ObjectOutputStream dos = new ObjectOutputStream(baos);
         dos.writeUnshared(dph);//here!!!!!

注:

  1. ByteArrayOutputStream的close中并未做任何事情,所以对baos.close也就没有作用
  2. ObjectOutputStream的close中会调用flush,写入到warpper的outputStream,并重置自己的position
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题