2013-07-25 76 views
0

我想在C#中使用System.Net.SocketsTcpClient類來編寫我的遊戲的網絡部分。TcpClient缺失數據

  • 每個更新服務器正在向客戶端發送信息。
  • 所有信息都內置到2kb數據包中,因此在1個更新中可以發送1-2-3-5-10個數據包。
  • 客戶正在檢查信息,如果信息有正確的格式 - 然後閱讀。
  • 一切工作正常,直到服務器開始嘗試發送太多的數據包。
  • 發生客戶端不時發送的數據包通常是20-50數據包的錯誤數據1。
  • 例如,1個更新的1-2個數據包通常會被正常接收,3-10個數據包會導致錯誤的數據流更新。
  • 如果我一次啓動多個客戶端,應該從服務器獲得相同的數據流 - 它們會獲得不同數量的成功和失敗數據流。

我在做什麼錯,我該如何逃避這個錯誤的數據流?

我只是在1毫秒內發送太多的數據,需要隨時發送它?

這是發送信息:

這是接收信息:

byte[] readBuffer; 
int byfferSize = 2048; 

private void StartListening() 
    { 
     client.GetStream().BeginRead(readBuffer, 0, bufferSize, StreamReceived, null); 
    } 

    private void StreamReceived(IAsyncResult ar) 
    { 
     int bytesRead = 0; 
     try 
     { 
      lock (client.GetStream()) 
      { 
       bytesRead = client.GetStream().EndRead(ar); // просмотр длины сообщения 
      } 
     } 
     catch (Exception ex) 
     { MessageBox.Show(ex.Message); } 

     //An error happened that created bad data 
     if (bytesRead == 0) 
     { 
      Disconnect(); 
      return; 
     } 

     //Create the byte array with the number of bytes read 
     byte[] data = new byte[bytesRead]; 

     //Populate the array 
     for (int i = 0; i < bytesRead; i++) 
      data[i] = readBuffer[i]; 

     //Listen for new data 
     StartListening(); 

     //Call all delegates 
     if (DataReceived != null) 
      DataReceived(this, data); 
    } 

它是主網絡的代碼。

+3

你爲什麼使用:lock(client.GetStream())??? –

+0

看起來錯誤的東西(不知道它會導致你的問題,但我懷疑它可能)是對BeginWrite的調用。這是一個ASYNC(非阻塞)調用,所以在寫入完成之前釋放鎖定,可能導致併發問題。嘗試用正常的Write()調用替換它。 – Xcelled194

+0

此外,使用Buffer.BlockCopy,而不是一個for循環,從readbuffer獲取字節到數據 – Xcelled194

回答

2

在收到數據後,我不知道您對數據做了什麼,但很有可能您沒有讀取連接中的所有數據。您有:

bytesRead = client.GetStream().EndRead(ar); 

無法保證您讀取的字節數是服務器發送的所有字節。例如,服務器可能發送了2,048字節,但當您調用Read時,僅有1,024字節可用。其餘的人仍然「在途中」。作爲documentation for NetworkStream.Read說:如可用,直到由尺寸參數

你可能會得到部分數據包中指定的字節數

讀操作讀取儘可能多的數據。如果您的DataReceived處理程序假定data緩衝區包含完整的數據包,那麼您將遇到問題。

要可靠地從網絡流中讀取數據,您需要知道您應該讀取多少數據,或者您需要記錄分隔符。有些事情必須確保,如果您希望在您嘗試處理完整數據包之前完成一個完整的數據包,您將獲得。你的代碼只是檢查bytesRead是不是0.如果是其他任何東西,你只需傳遞它。除非你的DataReceived處理程序知道如何緩衝部分數據包,否則這將是一個問題。

另一個說明,你真的不需要鎖定網絡流。除非你可以從同一個流中讀取多個線程。那將是災難性的。放開鎖。你不需要它。

+0

謝謝,吉姆,快速收到數據的樣子,看起來好像它是時時刻刻切割和混合的流,所以假設它是問題所在。將盡力改善明天收到的數據。 不能投票給你,至今還沒有足夠的聲望:-( –