2015-11-16 30 views
1

我正在实现带有服务器套接字机制的多人游戏。流中的套接字服务器流消息是混合的

  • 游戏运行在一个循环机制。
  • 服务器仅向每个连接的播放器播放任何消息。
  • 服务器为每个连接的播放器创建线程
  • 消息是JSON,它们每100ms从客户端发送一次。
  • 消息正在被服务器广播,客户端没有间隔读取。

这是服务器循环:

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名球员它工作正常,但更多的玩家连接更多的可能是得到这样的消息(或similiar破消息):

在消息LIK
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()锁定的过程,但我想保持它在游戏主循环同步的,我不认为这将有助于(我错了?)

回答

1

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

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

我试了一下:同步(这){p.getOut()writeUTF(inputMessage);}我认为原因可以将Java套接字实现躺在里面也许我使用错误类型的流? –

+0

同步(this)将不起作用,因为每个这是PlayerThread的不同实例。你需要在*全局/共享*对象上同步 – ControlAltDel

+0

你是对的,我改变它在流本身上同步后,它看起来更好。有性能问题,但我不确定它是由多个Java应用程序运行还是通过同步引起的。 –