使用TcpClient和TcpListener发送消息中的垃圾数据

时间:2016-05-25 16:25:44

标签: c# sockets tcpclient

我还有其他几个使用相同代码运行的网络代码,我以前从未见过这个代码。接收缓冲区中的剩余字节将填充\0\0\0\0\0\0\0\0\0\0\

我已经看过几次,但从未有过答案。

TcpListener tlist = new TcpListener(IPAddress.Parse(ip.ToString()), 27275);

一旦有连接。 。

byte[] byData = new byte[textBox.Text.Length];
byData = System.Text.Encoding.UTF8.GetBytes(textBox.Text);
client.Send(byData, 0, byData.Length, 0);

接收端:

byte[] bufferRec = new byte[56];
tc.Client.Receive(bufferRec, 0, 56, 0);
string output = Encoding.UTF8.GetString(bufferRec);

我通常使用的缓冲区大小为256,我实际上很少发送/接收256字节的数据,但我从未看到这些剩余的字节被垃圾数据填充,仅在这种情况下。

编辑:我当然可以简单地解析垃圾数据,但由于没有理由,它仍然是奇怪的行为。

1 个答案:

答案 0 :(得分:5)

你忽略了Socket.Receive的返回值,它告诉你已经读取了多少字节 - 这就像忽略Stream.Read的返回值一样。因此,您的缓冲区包含的字节数比实际收到的字节数多,因此您的字符串包含许多U + 0000个字符。例如,使用长度为16的缓冲区和文本" HELLO"

buffer: 48 45 4C 4C 4f 00 00 00 00 00 00 00 00 00 00 00
Return value: 5 (5 bytes received)
Encoding.UTF8.GetBytes(buffer): "HELLO\0\0\0\0\0\0\0\0\0\0\0"
Encoding.UTF8.GetBytes(buffer, 0, 5): "HELLO"

基本上,您应该只使用包含已接收数据的缓冲区部分。您也不应该假设对Receive(或Stream.Read)的单次调用将一次性读取所有数据,即使您的缓冲区大到足以接收它。 TCP是一种流媒体协议,所以围绕流媒体的所有常规警告都适用。如果您正在尝试编写面向消息的协议,则需要在TCP之上对其进行分层(例如,通过使用"标头"部分来指示数据中包含多少数据下一条消息)。

顺便说一句,直接从TcpClient使用底层套接字并不是一个好主意 - 使用它的要点是你可以使用更高级别的抽象,例如GetStream()