gpt4 book ai didi

Java Socket - 从线程更新实例变量列表

转载 作者:行者123 更新时间:2023-12-01 13:29:22 25 4
gpt4 key购买 nike

我有一个简单的 XO 游戏,其中有多个客户端互相玩 XO 国际象棋。我建立了一个与每个连接的客户端进行通信的服务器。 (当客户端连接到服务器时,我创建一个新类(实现 Runnable)处理该套接字然后启动线程...我有一个列表将所有客户端存储在外部类中)当客户端想要开始游戏时,他创建一个新的服务器并将房间的信息(他的名字、IP地址、端口...)发送到服务器。在服务器中,我有一个列表,它将该房间添加到列表中并将其发送给其他客户端。

    public class ServerController {
private ServerView view;
private ServerSocket myServer;
private int serverPort = 8881;
private List<ExchangeData> list;
private volatile List<Room> rooms;


public ServerController(ServerView view) {
this.view = view;
openServer(serverPort);
view.showMessage("TCP server is running...");
list = new ArrayList<ExchangeData>();
rooms = new ArrayList<Room>();
while (true) {
listening();
}

}

private void openServer(int portNumber) {
....
}

private void listening() {

try {
Socket clientSocket = myServer.accept();

ExchangeData ex = new ExchangeData(clientSocket);
Thread thread = new Thread(ex);
thread.start();
list.add(ex);

} catch (IOException e) {
System.out.print(e.toString());
}
}

class ExchangeData implements Runnable {
private Socket clientSocket;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private boolean run = true;

public ExchangeData(Socket socket) {
try {
clientSocket = socket;
oos = new ObjectOutputStream(clientSocket.getOutputStream());
ois = new ObjectInputStream(clientSocket.getInputStream());
} catch (Exception ex) {
System.out.println(ex.toString());
}


}

public void closeConnection() {
.....
}



public void sendData(Object o) {
try {

oos.writeObject(o);
} catch (Exception ex) {
view.showMessage(ex.toString());
}
}

public void run() {
try {

while (run) {
Object data = ois.readObject();
if (data instanceof Object[]) {
Object[] o = (Object[]) data;
String s = o[0].toString();

if (s.equalsIgnoreCase("Open Room")) {

Room r = (Room) o[1];
String username = r.getUsername();
InetSocketAddress isa = r.getIsa();
**rooms.add(r);**
List<Room> l = new ArrayList<Room>(rooms);

for (ExchangeData ex : list) {
ex.sendData(username + " Open A room at : "
+ isa);
**ex.sendData(rooms);**

}

} else if (s.equalsIgnoreCase("Close Room")) {
Room room = (Room) o[1];
rooms.remove(room);
List<Room> l = new ArrayList<Room>(rooms);
for (ExchangeData ex : list) {
ex.sendData(l);
}
}

} else if (data instanceof String) {
String s = data.toString();
if (s.equalsIgnoreCase("Quit")) {
stopThread();
list.remove(this);
closeConnection();

}
}

}

} catch (Exception ex) {
try {
stopThread();
list.remove(this);
} catch (ExceptionInInitializerError e) {
e.printStackTrace();

}
}
}
}

}

问题是当我执行 rooms.add(r) 时,其他线程似乎没有看到“更新”。例如:1)第一个玩家打开一个房间——房间大小为1;2)第二个玩家打开一个新房间 - 房间大小现在为 2 (我尝试在方法 sendData(Object o ) 中添加一些代码行,其中 println 房间的大小并且全部为 2。但是当行 ObjectoutputStream. write(o)被执行,它实际上写入了线程(第一个玩家)之前持有的房间的值,该值是1。如果我创建像 List l = new ArrayList(rooms) 这样的新列表,就像我对“Closing Room”所做的那样,然后发送此列表,它就可以工作。我不明白为什么?请有人向我解释一下。抱歉我的英语不好:(。

最佳答案

当您通过给定的 ObjectOutputStream 多次发送同一对象时,该流第一次会写入完整的对象状态,但之后仅发送对此对象的一些引用。

这允许使用循环引用发送复杂的对象图,而不会消耗太多带宽,也不会进入无限循环(发送引用 B 的 A,发送引用 A 的 B,发送引用 B 的 A,等等)。

因此,如果您想发送列表的新副本,则必须使用 reset()首先是ObjectOutputStream的方法。

关于Java Socket - 从线程更新实例变量列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21655869/

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