C# TcpClient未正确接收数据

C# TcpClient未正确接收数据,c#,.net,tcpclient,C#,.net,Tcpclient,我有一个客户机-服务器程序 我发送的数据如下: private void Sender(string s,TcpClient sock) { try { byte[] buffer = Encoding.UTF8.GetBytes(s); sock.Client.Send(buffer); }catch{} } byte[] buffer = new byte[PacketSize]; int size = client.Client.Receive(

我有一个客户机-服务器程序

我发送的数据如下:

private void Sender(string s,TcpClient sock)
{
   try
   {
      byte[] buffer = Encoding.UTF8.GetBytes(s);
      sock.Client.Send(buffer);
   }catch{}
}
byte[] buffer = new byte[PacketSize];
int size = client.Client.Receive(buffer);
String request = Encoding.UTF8.GetString(buffer, 0, size);
而在客户端,接收方式如下:

private void Sender(string s,TcpClient sock)
{
   try
   {
      byte[] buffer = Encoding.UTF8.GetBytes(s);
      sock.Client.Send(buffer);
   }catch{}
}
byte[] buffer = new byte[PacketSize];
int size = client.Client.Receive(buffer);
String request = Encoding.UTF8.GetString(buffer, 0, size);
问题是数据并非总是完全接收,有时它只是我发送的数据的一部分
PacketSize
是10240,比我发送的字节多。我还在两侧设置了SendBufferSize和ReceiveBufferSize

最糟糕的是,有时数据被完全接收


可能有什么问题?

TcpClient.Receive返回的
size
值与发送的缓冲字符串的长度不同。这是因为无法保证在调用
Receive
时,您将返回通过
Send
call发送的所有数据。这种行为是TCP工作方式的固有特性(它是一种流,而不是基于消息的数据协议)

使用较大的缓冲区无法解决此问题,因为您提供的缓冲区只能限制
接收
返回的数据量。即使您提供了1MB的缓冲区,并且有1MB的数据要读取,
Receive
也可以合法地返回任意数量的字节(即使只有1个字节)

您需要做的是确保在调用
Encoding.GetString
之前缓冲了所有数据。要做到这一点,首先需要知道有多少数据。因此,您至少需要在发送时写入字符串字节的长度:

  byte[] buffer = Encoding.UTF8.GetBytes(s);
  byte[] length = BitConverter.GetBytes(buffer.Length);
  sock.Client.Send(length);
  sock.Client.Send(buffer);
接收时,您将首先读取长度(已知固定大小:4字节),然后开始在临时缓冲区中缓冲其余数据,直到您有
length
字节(这可能需要任何数量的
Receive
调用,因此您需要
while
循环)。只有这样,您才能调用
Encoding.GetString
并取回原始字符串

对您观察到的行为的解释:


尽管操作系统的网络堆栈几乎没有保证,但实际上,它通常会给您一个TCP数据包随一个
Receive
调用带来的数据。由于TCP的MTU(最大数据包大小)允许大约1500字节的有效负载,只要字符串小于此大小,朴素的代码就可以正常工作。除此之外,它将被分成多个数据包,一个
接收
将只返回部分数据。

+1。不要忘记在tcp客户端/流上使用超时,否则,如果发送数据的应用程序行为不正常/存在网络问题,您的应用程序将挂起。@stefan:最好使用
Async
方法。但是让我们先把基本知识弄清楚:)@Jon使用异步是的,但这确实取决于应用程序。最好也有一个开始字节标识符,以确保同步。因此,当您读取了预期的所有字节后,下一个字节应该是一个已知值,后跟下一条消息(或EOF)。@FlappySocks:为什么?TCP保证数据的接收与发送完全相同,或者根本不相同。一个神奇的记号笔可能会让你感觉更自信,但这有技术上的原因吗?