Java套接字-接收不同对象的客户端
所以我想用Java制作一个使用套接字的纸牌游戏。我有一个“PlayerState”对象,它保留了大厅中的所有玩家或准备好玩的玩家。问题是,即使服务器为所有客户机发送相同的对象,所有客户机也会收到一个包含错误数据的不同对象。。。让我解释一下 这就是服务器中发送对象的方法:Java套接字-接收不同对象的客户端,java,sockets,stream,Java,Sockets,Stream,所以我想用Java制作一个使用套接字的纸牌游戏。我有一个“PlayerState”对象,它保留了大厅中的所有玩家或准备好玩的玩家。问题是,即使服务器为所有客户机发送相同的对象,所有客户机也会收到一个包含错误数据的不同对象。。。让我解释一下 这就是服务器中发送对象的方法: private void sendToAll(PlayersState playersState){ resetLists(playersState.getLobbyPlayers(),playersState.getR
private void sendToAll(PlayersState playersState){
resetLists(playersState.getLobbyPlayers(),playersState.getReadyPlayer());
Iterator it = clientOutputStreams.iterator();
while (it.hasNext())
try {
ObjectOutputStream writer = (ObjectOutputStream) it.next();
writer.writeObject(playersState);
writer.flush();
System.out.println(playersState.getLobbyPlayers());
} catch (Exception ex) {
}
}
这是客户端中接收对象的方法
private void whileChatting() throws IOException {
sendMessage("&nume"+nume);
do {
try {
Object object = input.readObject();
if(object instanceof String)
showMessage("\n" + (String) object);
else if(object instanceof PlayersState){
System.out.println(((PlayersState) object).getLobbyPlayers());
PlayersState actualPlayerState = new PlayersState();
actualPlayerState.setReadyPlayer(((PlayersState) object).getReadyPlayer());
actualPlayerState.setLobbyPlayers(((PlayersState) object).getLobbyPlayers());
resetLists(actualPlayerState.getLobbyPlayers(),actualPlayerState.getReadyPlayer());
}
} catch (ClassNotFoundException var2) {
showMessage("Unknown data received!");
}
} while(!message.equals("SERVER - END"));
}
这就是对象(在客户端和服务器中都可用)
这里一切正常。但这是客户收到的:
客户端1(用户1):
客户端2(用户2)
客户端3(用户3)
为什么客户端不接收所有相同的数据?PlayerState不是可变类,因此您应该在多线程上同步它。如下所示:
tresetLists(playersState.getLobbyPlayers(),playersState.getReadyPlayer());
Iterator it = clientOutputStreams.iterator();
byte[] sendBytes=null;
synchronized (playersState) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(playersState);
sendBytes = bos.toByteArray();
oos.close();
}
while (it.hasNext())
try {
ObjectOutputStream writer = (ObjectOutputStream) it.next();
writer.write(sendBytes);
writer.flush();
System.out.println(playersState.getLobbyPlayers());
} catch (Exception ex) {
}
在上面的代码中,为了提高性能和减少锁的保持时间,我们锁定了playersState
,只需将其串行化到sendBytes
数组中一次。
当然,您应该随时同步
playersState
,就像调用另一个线程上的getLobbyPlayer
和getReadyPlayer
。当服务器将playersState
发送到客户端时,playersState是否已更改。这是什么意思?您在服务器中使用多个线程吗?如果是这样,您如何同步对PlayersState
实例的访问?是的,我使用多线程,但这是我的第一个此类项目,我不知道如何同步应该在哪里添加锁变量?我更新我的答案,并且不使用ReentrantLock
,只需使用synchronized
。当您访问同一个PlayersState
实例时,您应该同步它。现在服务器在java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2917)在java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1502)给我一个EOFEException java.io.io.EOFEException位于sample.Main$newClient.run(Main.java:258)处的java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)位于java.lang.Thread.run(Thread.java:748)PlayerState
绝对是可变的。也许你想写“…不是一个不可变的类…”另外,我在OPs代码中没有看到任何线程的证据,所以我不确定你是如何得出这是一个同步问题的结论的。所以我尝试用一个简单的映射来更改整个对象,结果是一样的。。。
[user1, user2, user3]
[user1, user2, user3]
[user1, user2, user3]
[user1]
[user1]
[user1]
[user1,user2]
[user1,user2]
[user1,user2,user3]
tresetLists(playersState.getLobbyPlayers(),playersState.getReadyPlayer());
Iterator it = clientOutputStreams.iterator();
byte[] sendBytes=null;
synchronized (playersState) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(playersState);
sendBytes = bos.toByteArray();
oos.close();
}
while (it.hasNext())
try {
ObjectOutputStream writer = (ObjectOutputStream) it.next();
writer.write(sendBytes);
writer.flush();
System.out.println(playersState.getLobbyPlayers());
} catch (Exception ex) {
}