ObjectInputStream始终检索空List

时间:2017-01-31 11:54:25

标签: java objectinputstream objectoutputstream

我正在开发一个Client-Server项目(您可以调用它" 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 -Stackoverflow- to the list
I'm going to send: [Stackoverflow]
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: Stackoverflow
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 : []

如果我用&#34替换sendMsg()中的lstr.clear(); lstr = new LinkedList();&#34;它应该工作,但我不知道为什么:(

客户端日志(修复后):

 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: Stackoverflow
 I received o : [StackOverflow]
 Adding:StackOverflow
 I received o : []
 I received o : []
 I received o : []
 I received o : []

如何解释这种行为?

1 个答案:

答案 0 :(得分:5)

序列化协议保留了对象标识。

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

因此,流只会在您第一次发送时包含列表的状态,即为空。

当您稍后将内容添加到列表并再次写入列表时,将无法获取该列表。该流只会包含一个标签,上面写着“再次列出该列表”。

当您从list.clear()更改为创建一个全新的列表实例时,您可以解决此问题:现在,在编写本文时,每个列表都会使用其数据写入流。

相关问题