2015-07-21 198 views
2

我有一個服務器端客戶端應用程序,客戶端將圖像數據傳輸到服務器。我有以下結構:TCP服務器接收比預期更多的數據

客戶:

private void SerializeAndSendMessage(Message msg) { 
     BinaryFormatter formatter = new BinaryFormatter(); 
     MemoryStream stream = new MemoryStream(); 
     formatter.Serialize(stream, msg); 
     byte[] buffer = stream.ToArray(); 

     if (clientSocket != null) 
     { 
      if (clientSocket.Connected) 
      { 
       clientSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, SendCallback, null); 
      } 
     } 
    } 

private void SendCallback(IAsyncResult ar) { 
     try 
     { 
      clientSocket.EndSend(ar); 
      Debug.WriteLine("Message sent."); 
     } 
     catch (Exception ex) 
     { 
      // 
     } 
    } 

服務器:

private void ReceiveCallback(IAsyncResult ar) 
    { 
     try 
     { 
      int received = clientSocket.EndReceive(ar); 
      Array.Resize(ref buffer, received); 
      BinaryFormatter formatter = new BinaryFormatter(); 

      MemoryStream stream = new MemoryStream(buffer); 

      object obj = null; 
      stream.Position = 0; 
      try 
      { 
       obj = formatter.Deserialize(stream); 
      } 
      catch (Exception ex) 
      { 
       // 
      } 

      // processing data 

      Array.Resize(ref buffer, clientSocket.ReceiveBufferSize); 
      clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallback, null); 
     } 
     catch (Exception ex) 
     { 
      // 
     } 
    } 

我期待發生的事情:

  1. 服務器從客戶端
  2. 客戶開始接受數據發送大小爲X的數據
  3. 服務器接收與大小X的數據並開始處理它
  4. 客戶仍然在此期間發送數據
  5. 服務器沒有收到這個數據
  6. 服務器做處理接收到的數據,現在開始從客戶
  7. 接收
  8. 轉到2

正在發生的事情:

  1. SER版本開始從客戶端接收數據
  2. 客戶端發送數據與大小X
  3. 服務器接收與大小X的數據,並開始處理它
  4. 客戶端在此期間仍在發送數據
  5. 服務器不接收該數據
  6. 服務器完成處理所接收的數據和現在開始從客戶端接收
  7. 客戶端發送第N個數據包大小爲X
  8. 服務器接收大小爲M * X
  9. 的數據3210

這顯然會導致服務器上的緩衝區被填滿並且無法反序列化發送的包。我錯過了什麼?我能做些什麼來實現上述工作?

+0

嘗試閱讀套接字基礎知識。一個Send()不等於一個Receive()。您需要應用程序/成幀協議。像這樣的問題存在很多。 – CodeCaster

回答

0

TCP是一種流媒體協議。如果你在每一個客戶端之後做了幾次發送操作,TCP會將它們合併成一個段,因爲它正在嘗試填充MTU。

如果MTU已滿或TCP將發送,如果連續50ms的定時器結束,或者如果客戶端本身必須確認其從服務器接收到的數據包。

TCP是一個非常複雜的協議。這裏還有一個算法來計算窗口大小。此窗口大小也影響客戶端收到的分段的大小。

底線是因爲TCP是流協議,沒有你通過套接字接收數據包的概念。您收到,你必須追加到某種字節任意數量的接收緩衝區自己取決於你在做什麼。如果你想要的數據包,那麼你必須在前面加上你的服務器有一個長度字段發送並採取長短兼顧,以及數據。這當然會使代碼複雜化。或者如果你想保持簡單,只需使用UDP。 UDP確實支持數據包,如果數據包在某處不會丟失,則發送的數據將在接收方處以相同的大小接收。 但UDP不可靠,數據包可能會丟失。 TCP是可靠的,是面向連接的,但更復雜。

套接字編程通常不是初學者的話題。

相關問題