ArrayList <string>大小不在服务器和客户端之间保持</string>

时间:2014-02-08 20:01:47

标签: java serialization arraylist

我正在用Java编写服务器/客户端聊天应用程序。为了接收消息然后打印对话的总对话框,我将每个消息从客户端添加到字符串的ArrayList,然后将整个ArrayList发送回客户端,打印出整个会话。

我的问题是,即使我不断向服务器中的ArrayList添加元素,每当我将其发送到客户端时,大小都不会改变,只存储第一个元素。

服务器程序:

public class ArrayListServer {


  public static void main(String[] args) {
    int port = 8000;
    String me = "Server: ";
    ArrayList<String> convo = new ArrayList<String>();
    try {
      ServerSocket server    = new ServerSocket(port);
      System.out.println("Waiting for connection...");
      Socket client          = server.accept();
      System.out.println("Established connection.");
      ObjectInputStream  in  = new ObjectInputStream(client.getInputStream());
      ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
      int i = 0;
      // receive messages from client
      while (true) {
        String msgFromClient = (String)in.readObject();
        convo.add(msgFromClient);
        System.out.println(me + "size: " + convo.size());
        out.writeObject(convo);
      }
    } catch (IOException ioex) {
      System.out.println("IOException occurred.");
    } catch (ClassNotFoundException cnfex) {
      System.out.println("ClassNotFoundException occurred.");
    }

  }

}

客户计划:

public class ArrayListClient {

  @SuppressWarnings("unchecked")
  public static void main(String[] args) {
    int port = 8000;
    String me = "Client: ";
    Scanner input = new Scanner(System.in);
    ArrayList<String> convo = new ArrayList<String>();
    try {
      Socket client = new Socket("localhost", port);
      ObjectOutputStream toServer = new ObjectOutputStream(client.getOutputStream());
      ObjectInputStream fromServer = new ObjectInputStream(client.getInputStream());
      while (true) {
        System.out.print("> ");
        String msg = input.nextLine().trim();
        toServer.writeObject(msg);
        convo = (ArrayList<String>)fromServer.readObject();
        System.out.println(me + "size: " + convo.size());
      }
    } catch (UnknownHostException uhex) {
      System.out.println("UnknownHostException occurred.");
    } catch (IOException ioex) {
      System.out.println("IOException occurred.");
    } catch (ClassNotFoundException cnfex) {
      System.out.println("ClassNotFoundException occurred.");
    }
  }

}

当我运行服务器和客户端时,我的输出是:

> hi
Client: size: 1
> hi
Client: size: 1
> hi
Client: size: 1
> hi
Client: size: 1
> hi
Client: size: 1
> hi
Client: size: 1
> 

Server: Waiting for connection...
Server: Established connection.
Server: size: 1
Server: size: 2
Server: size: 3
Server: size: 4
Server: size: 5
Server: size: 6

我知道ArrayList<>String类都是可序列化的,所以我不知道为什么这不起作用。我认为它可能与我的输入/输出流有关,但是当我将它们声明为while循环的本地并在它结束时关闭它们时,我的程序将抛出IOException并停止。

我做错了什么?

2 个答案:

答案 0 :(得分:2)

我解决了。您使用相同的ObjectOutput和ObjectInput实例。 ObjectOutput尝试不重写之前看到的实例。因此,服务器第一次写入convo数组列表时,它会保留对它的引用。当您添加到它时,即使列表的内容执行,引用也不会更改。如果您在服务器中进行以下一行更改,则会向您证明这是问题所在:

out.writeObject( new ArrayList( convo ) );

以上不是一个很好的解决方案,因为ObjectOutputStream的参考图将继续增长一次迭代。但它会向您展示问题所在,以便您可以创建更好的解决方案。

更好的解决方案是在两侧循环中移动getInputStream和getOutputStream行。

此外,如果字符串不明显,因为在每次迭代时它们都是不同的对象引用。列表不是因为在服务器端每次都写入相同的引用,即使它发生了变化。

答案 1 :(得分:0)

太好了,我试着好几天才解决这个问题。谢谢!

您可以使用reset()方法“忘记”已知引用,如下所示:

out.writeObject(object);
out.reset();    
out.flush();