【问题标题】:ArrayList<String> size not persisting between server and clientArrayList<String> 大小在服务器和客户端之间不持久
【发布时间】:2014-02-08 20:01:46
【问题描述】:

我正在用 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&lt;&gt;String 类都是可序列化的,所以我不知道为什么这不起作用。我认为这可能与我的输入/输出流有关,但是当我将它们声明为 while 循环的本地并在其末尾关闭它们时,我的程序会抛出 IOException 并停止。

我做错了什么?

【问题讨论】:

  • 因为在客户端您不断重置列表,而在服务器端您正在向其中添加项目。
  • @DevZer0 这应该没问题,他/她期望将 整个 ArrayList 写入输出流。那么为什么看起来不是这样呢?
  • @user2864740 “陈旧代码”是什么意思?
  • @user2864740 哦,不。这两个类在它们自己的包中。我的另一个客户端/服务器应用程序也有这个问题。
  • 我不确定这是您的问题,但我注意到您在写入输出流后并未刷新它们。您可能希望在 out.writeObject() 之后添加一个 out.flush(),其中 out 是 out 和 serverOut。两边都需要。

标签: java serialization arraylist


【解决方案1】:

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

out.writeObject( new ArrayList( convo ) );

上述不是一个很好的解决方案,因为 ObjectOutputStream 的参考映射将不断增长一个迭代。但它会告诉您问题所在,以便您创建更好的解决方案。

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

如果字符串工作不明显,因为在每次迭代中它们都是不同的对象引用。 List 不是因为在服务器端您每次都编写相同的引用,即使它发生了变化。

【讨论】:

  • 太棒了!有了这些信息,我确信我可以找到解决方案。谢谢!
【解决方案2】:

太好了,我尝试了几天解决这个问题..谢谢!

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 2011-02-10
    • 2023-03-12
    • 1970-01-01
    • 2021-12-28
    相关资源
    最近更新 更多