2015-11-16 31 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應用程序運行還是通過同步引起的。 –