C# TCP数据包丢失问题:大字符串传输仅接收1400字节求助
解决TCP大字符串传输截断问题
这个问题我太熟了——你碰到的是TCP流式传输的典型坑!
问题根源
TCP是面向流的传输协议,不是像UDP那样的“数据包”协议。你调用NetworkStream.Read()时,它只会返回当前网络缓冲区里已经收到的字节数,而不是你发送的全部数据。1400字节左右刚好是大多数网络的MTU(最大传输单元)大小,所以大内容会被拆分成多个TCP分段发送,你的单次Read()只能拿到第一个分段的数据,剩下的就被留在缓冲区里没被读取(不是真的丢了)。
解决方案:确保读取完整数据
最可靠的解决方式是先发送数据的长度,再发送实际内容,让接收端明确知道要读取多少字节,然后循环读取直到拿到全部数据。
修改后的客户端代码
发送数据(新增长度前置逻辑)
public static string Senddata(string BarcodeText) { try { string textToSend = BarcodeText.ToString(); byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(textToSend); // 先发送数据长度(用4字节int表示,让接收端知道要读多少) byte[] lengthBytes = BitConverter.GetBytes(bytesToSend.Length); nwStream.Write(lengthBytes, 0, lengthBytes.Length); // 再发送实际内容 nwStream.Write(bytesToSend, 0, bytesToSend.Length); return "Success";//if sent } catch (Exception) { return "Fail";//if not sent } }
接收数据(改成循环读取完整内容)
public static string Getdata() { try { // 第一步:读取数据长度(固定4字节) byte[] lengthBuffer = new byte[4]; int bytesRead = nwStream.Read(lengthBuffer, 0, 4); if (bytesRead != 4) { return "Failed to read data length"; } int dataLength = BitConverter.ToInt32(lengthBuffer, 0); // 第二步:循环读取所有数据,直到凑够指定长度 byte[] dataBuffer = new byte[dataLength]; int totalBytesRead = 0; while (totalBytesRead < dataLength) { int read = nwStream.Read(dataBuffer, totalBytesRead, dataLength - totalBytesRead); if (read == 0) { // 连接意外断开 return "Connection closed prematurely"; } totalBytesRead += read; } str = Encoding.GetEncoding("ISO-8859-1").GetString(dataBuffer, 0, totalBytesRead); return str; } catch (Exception ex) { return $"Error receiving data: {ex.Message}"; } }
修改后的服务器端代码
接收数据(新增循环读取逻辑)
public static string GetDatafromClient() { try { nwStream = client.GetStream(); // 第一步:读取数据长度 byte[] lengthBuffer = new byte[4]; int bytesRead = nwStream.Read(lengthBuffer, 0, 4); if (bytesRead != 4) { return "-"; } int dataLength = BitConverter.ToInt32(lengthBuffer, 0); // 第二步:循环读取完整数据 byte[] buffer = new byte[dataLength]; int totalBytesRead = 0; while (totalBytesRead < dataLength) { int read = nwStream.Read(buffer, totalBytesRead, dataLength - totalBytesRead); if (read == 0) { return "-"; } totalBytesRead += read; } return Encoding.ASCII.GetString(buffer, 0, totalBytesRead); } catch (Exception) { return "-"; } }
发送数据(新增长度前置逻辑)
public static void SendDatatoClient(string DataToSend) { FileHandling.SaveToFile(DataToSend); byte[] bytesTosend = Encoding.GetEncoding("ISO-8859-1").GetBytes(DataToSend); // 先发送数据长度 byte[] lengthBytes = BitConverter.GetBytes(bytesTosend.Length); nwStream.Write(lengthBytes, 0, lengthBytes.Length); // 再发送实际内容 nwStream.Write(bytesTosend, 0, bytesTosend.Length); }
额外注意事项
- 编码一致性:你客户端发送用
ASCIIEncoding.ASCII,接收却用ISO-8859-1,服务器端刚好反过来,这可能导致乱码,建议统一编码(比如都用UTF-8或者ISO-8859-1)。 - 字节序问题:如果客户端和服务器端运行在不同架构的机器上(比如x86和ARM),
BitConverter的字节序可能不兼容,这种情况下可以手动指定大端/小端序来处理。
内容的提问来源于stack exchange,提问作者user8511293
相关产品推荐
相关产品推荐

