gpt4 book ai didi

java - 在简单的聊天程序中,服务器发送字符串的数组列表,但客户端接收旧值

转载 作者:行者123 更新时间:2023-11-30 04:06:53 25 4
gpt4 key购买 nike

我想创建一款带有服务器和多个客户端的简单游戏。服务器将有多个 Hashmap 和 Arraylist。服务器将这些广播给客户端,然后客户端可以一一修改这些值并将其发送回服务器,然后服务器将更新的值广播给所有客户端。

首先,我创建了服务器-客户端聊天应用程序。当客户端向服务器发送字符串消息时,服务器会将该字符串消息添加到其数组列表中,并将该数组列表广播给所有客户端。我已经使用了线程,以便多个客户端可以同时发送消息,但我还没有应用线程安全。

让我们来解决这个问题。当客户端第一次向服务器发送字符串时,服务器会很好地打印它,添加到它的数组列表中,然后将其广播给所有客户端,并且所有客户端也都可以看到。但是下次当客户端发送 String 消息时,服务器会接受它,添加到 arraylist 并广播它,但这一次所有客户端都会获得旧的 arraylist (仅包含一个首先添加的 String 的列表)。我在广播之前打印了 arraylist,它显示了修改后的值,但在客户端它显示仅包含一个条目的列表。

部分服务器代码

public class ServerGUI extends javax.swing.JFrame {

public static final int SERVER_PORT = 4000;
private ServerSocket ss;
ArrayList<String> al;
ArrayList<ClientHandler> clients;

public ServerGUI() {
initComponents();
setVisible(true);
al = new ArrayList<>();
clients = new ArrayList<>();
initNet();
}

private void initNet() {
Socket ds = null;
try {
ss = new ServerSocket(SERVER_PORT, 1);
while (true) {

ds = ss.accept();

clients.add(new ClientHandler(ds));
}
} catch (Exception e) {

System.out.println("shutting down server......");
}
}

class ClientHandler extends Thread {

private Socket ds;
private ObjectOutputStream out;
private ObjectInputStream in;

public ClientHandler(Socket ds) throws Exception {
this.ds = ds;
out = new ObjectOutputStream(ds.getOutputStream());
in = new ObjectInputStream(ds.getInputStream());
start();
}

public ObjectOutputStream getOut() {
return out;
}

public void run() {
try {
while (true) {
acceptData(in);
broadcastData();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("Finally called. socket closed");
if (ds != null) {
try {
ds.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

private void acceptData(ObjectInputStream in) throws Exception {
System.out.println("acceptData called by " + Thread.currentThread().getName());
String s = (String) in.readObject();
al.add(s);
jta.setText(al.toString());
}

private void broadcastData() throws Exception {
System.out.println("broadcast called by " + Thread.currentThread().getName());
System.out.println("al is : \n" + al);

for (ClientHandler clnt : clients) {
clnt.getOut().writeObject(al);
clnt.getOut().flush();
}
}

部分客户端代码

public class ClientGUI extends javax.swing.JFrame {

public static final int SERVER_PORT = 4000;
public static final String SERVER_IP = "127.0.0.1";
private Socket s1;
private ObjectOutputStream out;
private ObjectInputStream in;
private ArrayList<String> al;

public ClientGUI() {
initComponents();
setVisible(true);
initNet();
}

private void initNet() {
try {
s1 = new Socket(SERVER_IP, SERVER_PORT);
out = new ObjectOutputStream(s1.getOutputStream());
in = new ObjectInputStream(s1.getInputStream());
System.out.println("connected to server");

new ReadData();

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

class ReadData extends Thread {

public ReadData() {
start();
}

public void run() {
System.out.println("client thread started");
try {
while (true) {
al = (ArrayList<String>) in.readObject();
System.out.println("client read completed, al is "+al);

jta.setText(al.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void textFieldActionPerformed(java.awt.event.ActionEvent evt) {
try {
out.writeObject(jtf.getText());
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}

最佳答案

这是正常行为。如果您多次将同一个对象(您的 ArrayList)发送到给定的 ObjectOutputStream,该流将在第一次发送完整的对象,并且下次仅发送对此对象的引用。这使得发送对象图不会消耗太多带宽,也不会进入无限循环,因为 a 引用 b,而 b 也引用 a .

为了确保ArrayList再次发送,您需要调用reset()ObjectOutputStream上。

关于java - 在简单的聊天程序中,服务器发送字符串的数组列表,但客户端接收旧值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20543403/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com