Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java套接字-接收不同对象的客户端_Java_Sockets_Stream - Fatal编程技术网

Java套接字-接收不同对象的客户端

Java套接字-接收不同对象的客户端,java,sockets,stream,Java,Sockets,Stream,所以我想用Java制作一个使用套接字的纸牌游戏。我有一个“PlayerState”对象,它保留了大厅中的所有玩家或准备好玩的玩家。问题是,即使服务器为所有客户机发送相同的对象,所有客户机也会收到一个包含错误数据的不同对象。。。让我解释一下 这就是服务器中发送对象的方法: private void sendToAll(PlayersState playersState){ resetLists(playersState.getLobbyPlayers(),playersState.getR

所以我想用Java制作一个使用套接字的纸牌游戏。我有一个“PlayerState”对象,它保留了大厅中的所有玩家或准备好玩的玩家。问题是,即使服务器为所有客户机发送相同的对象,所有客户机也会收到一个包含错误数据的不同对象。。。让我解释一下

这就是服务器中发送对象的方法:

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) {
        }