ObjectInputStream 总是检索一个空列表

ObjectInputStream always retrieves a empty List

我正在处理一个客户端-服务器项目(您可以称它为 "Broadcast Chat"),但我遇到了 ObjectInputStream 的问题。 它总是给我检索一个空列表,我找到了一个解决方案,但我不知道它为什么有效...

这是错误代码(检查服务器的 sendMsg() 函数):

服务器:

public class CoreServer implements Runnable {
    private Socket sock;
    private ServerConnect sc;
    private ObjectOutputStream oos;
    private ObjectInputStream ois;
    private boolean running=true;
    private List<String> lstr;
    public CoreServer(Socket sock, ServerConnect sc) {
        this.sock=sock;
        this.sc=sc;
    }

    @Override
    public void run() {
        lstr=new LinkedList<String>();
        try {
            oos= new ObjectOutputStream(sock.getOutputStream());
            ois=new ObjectInputStream(sock.getInputStream());


        } catch (IOException e) {
            e.printStackTrace();
        }
        while (running){
            Object o=null;
            try {
                o= ois.readObject();

            } catch (ClassNotFoundException | IOException e) {
                // TODO Auto-generated catch block
                sc.remove(this);
                stop();
            }
            if (Integer.class.isInstance(o)){
                try {
                    int num= (Integer) o;
                    if(num==0){
                        sendMsg();
                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

            else if (String.class.isInstance(o)){
                System.out.println("String Received");
                String ss= (String) o;
                sc.readyToSend(ss);

            }


        }
    }



    public void sendMsg() throws IOException{
        try {
            System.out.println("I'm going to send: "+lstr);
            oos.writeObject((Object)lstr);
            oos.flush();
            lstr.clear();
            // If I replace lstr.clear() with "lstr=new LinkedList();" it works as it should.


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void addMsg(String text){
        System.out.println("I will add -"+text+"- to the list");
            lstr.add(text);

    }



}

客户:

public class ClientConnect implements Runnable {
    private Socket sock;
    private boolean running=true;
    private ObjectInputStream ois;
    private ObjectOutputStream oos;
    private boolean first=true;
    private Object o;
    private ClientFrame cf;

    public ClientConnect(Socket sock, ClientFrame cf){
        this.sock=sock;
        this.cf=cf;
    }

    @Override
    public void run() {
        if (first){
            try {
                oos= new ObjectOutputStream(sock.getOutputStream());
                ois= new ObjectInputStream(sock.getInputStream());
                first=false;

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        while (running){
            try {
                oos.writeObject(new Integer(0));
                oos.flush();
            } catch (IOException e) {
                JOptionPane.showMessageDialog(null, "Connection error");
                this.stop();
                System.exit(1);
            }

            try {
                o=ois.readObject();
                System.out.println("I received o : "+(List)o);
            } catch (ClassNotFoundException | IOException e) {

                JOptionPane.showMessageDialog(null, "Server offline");
                System.exit(1);
            }

                if(List.class.isInstance(o)){
                    List<String> l=null;
                    l=(List<String>) o;
                    Iterator<String> it= l.iterator();
                    while (it.hasNext()){
                        String s=it.next();
                        System.out.println("Adding:"+s);
                        cf.history.append(s+ "\n"); //this function will show the received content on a JTextArea
                }
            }





            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public void send(String text){
        if (!text.equals("")){
            try {
                oos.writeObject(text);
                oos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }


        }


    }


}

客户端应该将我写的东西发送到服务器,然后服务器将向每个连接的客户端发送相同的消息。 这是我写东西时服务器端和客户端发生的情况:

服务器日志:

Waiting client
Found one client
Waiting client //The Server is multithreaded and is waiting for another client to connect
Waiting client
I'm going to send: []
I'm going to send: []
I'm going to send: []
String Received
I will add -Hello- to the list
I'm going to send: [Hello]
I'm going to send: []
I'm going to send: []
I'm going to send: []
String Received
I will add -Whosebug- to the list
I'm going to send: [Whosebug]
I'm going to send: []
I'm going to send: []
I'm going to send: []
I'm going to send: []

客户端日志:

I received o : []
I received o : []
I received o : []
You wrote: Hello
I received o : []   <-- it can't read the list that the server sent to me.
I received o : []
I received o : []
I received o : []  
You wrote: Whosebug
I received o : []  <-- it can't read the list that the server sent to me.
I received o : []
I received o : []
I received o : []
I received o : []

如果我将 sendMsg() 中的 lstr.clear() 替换为 "lstr=new LinkedList();",它会正常工作,但我不知道为什么 :(

客户端日志(修复后):

 I received o : []
 I received o : []
 I received o : []
 You wrote: Hello
 I received o : [Hello]
 Adding:Hello
 I received o : []
 I received o : []
 I received o : []  
 You wrote: Whosebug
 I received o : [Whosebug]
 Adding:Whosebug
 I received o : []
 I received o : []
 I received o : []
 I received o : []

如何解释这种行为?

序列化协议保留对象身份。

如果您重复写入同一个对象,它不会再次序列化其内容,流将只包含一个反向引用以指示您再次写入同一个对象。

因此,流将仅包含列表在您首次发送时的状态,即为空。

当您稍后将内容添加到列表并再次编写列表时,不会被拾取。该流将只包含一个标签,上面写着 "that list from before again".

当您从 list.clear() 更改为创建一个全新的列表实例时,您解决了这个问题:现在,每个列表都在写入时连同其数据一起写入流中。