2017-04-05 63 views
1

通常我能夠自行解決問題,但我必須再次尋求幫助。如果事情不一致,我會提前道歉,因爲看起來我有點發燒。Socket WriteLine/ReadLine不匹配

我目前在XNA中製作真正簡單的遊戲。這是一個2D高射炮。唯一的行動是玩家射擊子彈。事情是,我想讓它成爲多人遊戲(玩家在同一個網絡中)。

我已經考慮以下方法:

  1. 一個玩家的主機服務器

    • 服務器持有約每一個球員和子彈
    • 服務器創造了新的世界的位置信息(組成球員和子彈)並更新它像這樣的新線程:

      while (true) 
          { 
           lock (world) world.update(); 
           Thread.Sleep(worldUpdatePeriod); 
          } 
      
    • 服務器爲每個有需要處理

  2. 玩家連接到服務器的玩家創造了新的主題

    • 他們應定期接收來自服務器的信息,他們應借鑑:

      class Asset 
      { 
          string type; 
          Vector2 position; 
      } 
      
    • 他們應該能夠從鍵盤發送輸入和鼠標移動和射擊。

現在的地步。玩家能夠發送三種類型的消息到服務器:

  • 「可以閱讀」
  • 「MOUSE」
  • 「鍵盤」

    string header = "CAN READ"; 
    lock (streamWriter) { streamWriter.WriteLine(header); } 
    

服務器,在單獨爲每個客戶端線程等待郵件

streamReader = new StreamReader(networkStream); 
streamWriter = new StreamWriter(networkStream); 
streamWriter.AutoFlush = true; 

while (true) 
{ 
    if (networkStream.DataAvailable) 
    { 
     string header; 
     lock (streamReader) 
     { 
      header = Convert.ToString(streamReader.ReadLine()); 
      Console.WriteLine($"Header received: {header}"); 
      handleHeader(header); 
     } 
    } 
} 

現在,如果標題是,例如, 「可以閱讀」

  1. 服務器

    case "CAN READ": 
        if (streamWriter.BaseStream.CanRead) 
        { 
         lock (streamWriter) 
         { 
          streamWriter.WriteLine(server.world.assets.Count); 
    
          foreach (var asset in server.world.assets) 
          { 
           streamWriter.WriteLine(asset.type); 
           streamWriter.WriteLine(asset.position.X); 
           streamWriter.WriteLine(asset.position.Y); 
          } 
         } 
        } 
        break; 
    
  2. 客戶

    int assetCount = Convert.ToInt32(streamReader.ReadLine()); 
    List<Asset> receivedAssets = new List<Asset>(); 
    
    lock (streamReader) 
    { 
    
        for (int i = 0; i < assetCount; i++) 
        { 
         string type = Convert.ToString(streamReader.ReadLine()); 
         int x = Convert.ToInt32(streamReader.ReadLine()); 
         int y = Convert.ToInt32(streamReader.ReadLine()); 
    
         receivedAssets.Add(new Asset(type, new Vector2(x, y))); 
        } 
        return receivedAssets; 
    } 
    

當然,客戶端類和handleClient類的都單獨的streamReaders和streamWriters。

你的想法。我試圖將來自服務器的每個WriteLine()與來自客戶端的ReadLine()匹配,等等。它工作正常!直到我將用戶輸入添加到混合物中。

有一次,我送鍵盤輸入(如上圖所示匹配),它似乎工作,偶爾System.FormatException,這意味着一些的ReadLine()讀取錯誤的WriteLine()。我能夠抓住並重試。

所有的一切都去地獄一次我送鼠標輸入,以及。不匹配的例外會變得越來越頻繁,直到「遊戲」無法播放。所以我想知道我的方法是否有問題。我對這個問題的長度表示歉意,我試圖簡明扼要,但也覺得需要提供上下文。非常感謝,如果您完成了這個任務,我會很樂意回答任何其他問題,因爲我在過去幾天試圖解決這個問題。

+0

TCP連接? TCP是一種流媒體協議,沒有消息邊界的概念。查看http://stackoverflow.com/questions/17446491/tcp-stream-vs-udp-message只是一個類似的問題。 –

回答

1

我讀過,安德魯與我提供的鏈接,我已經能夠使它發揮作用。怎麼樣?使用TCP客戶端(建立連接,從客戶端讀取輸入)和UDP客戶端(向每個客戶端廣播資源)。只是在帖子中提到,如果有人在將來遇到這樣的問題,我非常懷疑。

乾杯!