java - 流中的套接字服务器流消息是混合的

标签 java json sockets stream message

我正在使用服务器套接字机制实现多人游戏。

  • 游戏以单循环机制运行。
  • 服务器仅向每个连接的玩家广播任何消息。
  • 服务器为每个连接的玩家创建线程
  • 消息是 JSON,它们每 100 毫秒从客户端发送一次。
  • 消息正在由服务器广播并由客户端无间隔地读取。

这是服务器循环:

    while (true) {
                try {
                    System.out.println("LISTENING...");
                    Socket clientSocket = serverSocket.accept();
                    System.out.println("GOT CONNECTION");

                    PlayerThread playerThread = new PlayerThread(clientSocket);
                    playerThread.start();
                } catch (IOException e) {
                    LOGGER.log(Level.SEVERE, "Exception occured on server");
                    break;
                }
            }

这是 PlayerThread 循环:

        while (true) {
            try {
                String inputMessage = in.readUTF();
                System.out.println("GOT: " + inputMessage);
                JsonNode jsonNode = objectMapper.readTree(inputMessage);
                String senderName = jsonNode.get("senderName").asText();

                if (!players.contains(this)) {
                    playerName = senderName;
                    players.add(this);
                }

                for (PlayerThread p : players) {
                    p.getOut().writeUTF(inputMessage);
                }

最后收听消息:

public void listen() {
        if (connected) {
            try {
                if (in.available() > 0) {
                    String inputMessage = in.readUTF();
                    System.out.println("GOT MESSAGE: " + inputMessage);
                    handleMessages(inputMessage);
                }
            } catch (IOException e) {
                LOGGER.log(Level.INFO, "Connection lost");
                connected = false;
            }
        } else
            LOGGER.log(Level.INFO, "Player is not connected");
    }

上面的方法在主游戏循环中运行。它检查 inputStream 中是否有内容,然后读取它。

正确的消息是这样的:

GOT MESSAGE: {"type":"UPDATE_STATE","content":null,"senderName":"GRACZ 52","posX":10.0,"posY":5.0}

当有 2 个玩家时,它可以正常工作,但是连接的玩家越多,就越有可能收到这样的消息(或类似的损坏消息):

GOT MESSAGE: 0} U{"type":"UPDATE_STATE","content":null,"senderName":"GRACZ 65","posX":10.0,"posY":5.0}

GOT MESSAGE: {"type":"UPDATE_STATE","content":null,"senderName":"GRACZ 24","pos

消息中存在不同的错误,如 Y 字母、半消息或一行中有多个消息。为什么会发生这样的事情呢?看起来当有更多玩家并且他们写入服务器端的输出流时,该流还没有被读取,因此他们正在追加和追加。但它并没有解释为什么会有破损,最重要的是,如何解决它?

我可以将读取流移动到另一个线程,因为 in.readUTF() 锁定进程,但我想在主游戏循环中保持它同步,我认为这不会有帮助(我错了吗?)

最佳答案

您需要同步所有 PlayerThread 之间通用的对象上的写入循环,以便消息不会交错。

         synchronized(/*Should be a "global" server object*/) {
           for (PlayerThread p : players) {
                p.getOut().writeUTF(inputMessage);
            }
         }

关于java - 流中的套接字服务器流消息是混合的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33739468/

相关文章:

json - 包含空值的 BsonDocument 的 Newtonsoft.Json.JsonConvert.SerializeObject 因 InvalidCastException 而失败

javascript - 如何安全地 XSS 编码来自 PHP 的不受信任的数据,通过 AJAX 通过 javascript 注入(inject)到 DOM 中?

c# - 构建一个 JsonConstructor 以便能够反序列化我的对象

javascript - 将 Socket.io 与 Node.js、Express 和 Jade 结合使用

同一台机器上的两个进程可以连接到同一个端口吗?

Java 套接字应用程序在尝试发送文件时发送额外的字节

java - 序列化 JTable 的 TableModel

java - 将servlet连接到数据库as400

java - 如何在 Java Spring 中将查询映射到 POJO?

java - 如何将本地jar文件添加到Maven项目中?