我正在用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并停止。
我做错了什么?
答案 0 :(得分:2)
我解决了。您使用相同的ObjectOutput和ObjectInput实例。 ObjectOutput尝试不重写之前看到的实例。因此,服务器第一次写入convo数组列表时,它会保留对它的引用。当您添加到它时,即使列表的内容执行,引用也不会更改。如果您在服务器中进行以下一行更改,则会向您证明这是问题所在:
out.writeObject( new ArrayList( convo ) );
以上不是一个很好的解决方案,因为ObjectOutputStream的参考图将继续增长一次迭代。但它会向您展示问题所在,以便您可以创建更好的解决方案。
更好的解决方案是在两侧循环中移动getInputStream和getOutputStream行。
此外,如果字符串不明显,因为在每次迭代时它们都是不同的对象引用。列表不是因为在服务器端每次都写入相同的引用,即使它发生了变化。
答案 1 :(得分:0)
太好了,我试着好几天才解决这个问题。谢谢!
您可以使用reset()方法“忘记”已知引用,如下所示:
out.writeObject(object);
out.reset();
out.flush();