2013-01-24 80 views
0

好吧,爲了我的遊戲,我建立了一個服務器/客戶端對等連接,來回發送位置等。異步TCP服務器/客戶端不可靠的數據包?

雖然我的消息實際上並沒有發送那麼快,也不可靠。如在弦的部分丟失,有時僅發送停止和線程犯規繼續(不知道爲什麼).T

反正我Recieving代碼是在這裏:

public void RecieveAsync() 
    { 

     if (netStream == null) netStream = Server.GetStream(); 


     if (netStream.DataAvailable == false) return; 

     netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, new AsyncCallback(recieveCallBack), netStream); 




    } 


    public void recieveCallBack(IAsyncResult ar) 
    { 
     //try 
     //{ 

     String content = String.Empty; 

     Console.WriteLine("Stuck trying to get data"); 

     int rec = netStream.EndRead(ar); 



     if (rec > 0) 
     { 


       Console.WriteLine(Encoding.ASCII.GetString(
    ReadBuffer, 0, rec)); 

      string packet = Encoding.ASCII.GetString(
    ReadBuffer, 0, rec); 
       bool completedPacket = false; 
       int appendTo = rec; 

       if (packet.Contains("<eof>")) 
       { 
        appendTo = packet.IndexOf("<eof>"); 
        packet.Replace("<eof>", ""); 
        completedPacket = true; 
       } 

       SB.Append(packet, 0, appendTo); 

       // Check for end-of-file tag. If it is not there, read 
       // more data. 

       content = SB.ToString(); 



      if (completedPacket) 
      { 
       // All the data has been read from the 
       // client. Display it on the console. 


       if (DataRecieved != null) 
       { 
        string RecievedData = SB.ToString(); 

        DataRecieved(RecievedData); 

        netStream.Flush(); 

        Array.Clear(ReadBuffer, 0, ReadBuffer.Length); 
        ReadBuffer = new byte[1024]; 
       } 

       SB.Clear(); 

       // Echo the data back to the client. 
      } 
      else 
      { 
       // Not all data received. Get more. 
       Array.Clear(ReadBuffer, 0, ReadBuffer.Length); 
       ReadBuffer = new byte[1024]; 
       netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream); 
      } 


     } 

    } 

而且我發送代碼在這裏:

public void Send(byte[] data, int index, int length) 
    { 
     //add data as state 

     //socket.NoDelay = true; 

     if (netStream == null) netStream = TcpClient.GetStream(); 

     netStream.BeginWrite(data, 0, length, sendCallback, netStream); 




    } 

    private void sendCallback(IAsyncResult ar) 
    { 
     //try 
     //{ 
      netStream.EndWrite(ar); 

      //if (ar.AsyncState != null) 
      //{ 
      // byte[] buffer = (byte[])ar.AsyncState; 
      // socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, sendCallback, null); 
      // return; 
      //} 

      if (OnSend != null) 
      { 
       OnSend(this); 
      } 

      netStream.Flush(); 


     //catch (Exception ex) 
     //{ 
     // System.Windows.Forms.MessageBox.Show(ex.ToString()); 
     // return; 
     //} 
    } 

數據包在Encoding.ASCII.Getbytes下。

並且服務器和客戶端都在帶有Thread.Sleep(1)的while(true)線程中更新。

+0

另外是這樣顯示數據包的結尾 – user1965626

+0

假設在讀取之間被分割? – spender

+0

它也在我看來,你正在合併數據包一旦發送,並刪除框架(''); DataReceived可能不僅僅是一個「數據包」(在您的術語中,而不是底層的網絡術語),並且將無法解讀它。從根本上說,這裏要做的事情就是記錄你收到的一切,以及你正在處理的一切 - 這樣你就可以看到發生了什麼問題。 –

回答

0

由於您試圖逐位重構字符串(如果您使用更常見的多字節編碼(如UTF8),此方法會中斷),因此您的方法很脆弱。

正如我的評論所述,你可能會錯過你的<eof>,因爲它被分成兩次讀取。

IMO,一個較好的方法是用標籤在前面的長度字段(4字節INT)你的消息,讓你不必在想,如果它的完成沒有搞清楚的消息結束躡手躡腳周圍。

只需將所有讀取內容倒入MemoryStream中,直至達到指定的消息長度,然後使用您認爲合適的任何編碼解碼MemoryStream的內容。

+0

標記我的消息是什麼意思?在發送一個數據包之前,它表示長度? – user1965626

+0

@ user1965626:是的,確切的說......一個包含4個字節的「數據包」來表示長度,所以一個讀取包含1.讀取指示長度的幾個字節(如果它是一個int,則可能是4)2.讀取length '字節來獲得你的信息 – spender