2015-07-21 209 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是可靠的,是面向连接的,但更复杂。

套接字编程通常不是初学者的话题。

相关问题