【发布时间】:2017-04-09 13:57:19
【问题描述】:
我有一个关于通过 TCP 类发送和接收消息的顺序的简单问题,我找不到任何 100% 的答案,而且我的英语还不够好。
如果我有以下示例:
服务器:
IPAddress IP = IPAddress.Parse("127.0.0.1");
int Port = 13000;
TcpListener Server = new TcpListener(IP, Port);
TcpClient Client = Server.AcceptTcpClient();
NetworkStream Stream = Client.GetStream();
Stream.Write(Buffer1, 0, 4);
//random time
Stream.Write(Buffer2, 0, 4);
//random time
Stream.Write(Buffer3, 0, 4);
和客户:
TCPClient Client = new TcpClient("127.0.0.1", 13000);
NetworkStream Stream = Client.GetStream();
Stream.Read(A, 0, 4);
//random time
Stream.Read(B, 0, 4);
//random time
Stream.Read(C, 0, 4);
是否 100% 确定我会得到 A = Buffer1、B = Buffer2、C = Buffer3?
【问题讨论】:
-
不!您必须检查
Stream.Read的返回值以查看您实际获得了多少字节。 TCP 是 ordered 的(意思是,您可以保证按照发送它们的顺序接收字节)而且也是 stream-based 的(意思是,不保证字节的打包)。更明确地说:TCP 没有消息。如果你想要消息,你必须自己构建它们(用长度作为前缀是最常见的方法)。请参阅任何有关网络代码的教程,了解如何编写正确的接收循环。 -
我已经实现了这个前缀,我的消息的前 4B 是消息的长度,所以在另一边我读取了前 4B,然后将 NumberOfBytesToRead 设置为该数字以进行另一次读取。我只是想确认您可能在评论的第一部分中回答的消息的顺序:)
-
小心:如果你要求 4 个字节,你甚至不能保证得到 4 个字节(它们可以跨数据包拆分),所以即使读取长度也必须在循环中完成,直到你有那些4字节。然后您需要再次循环以获取完整消息。弄错这个错误可能是网络编程中最常见的错误,而且特别狡猾,因为这种代码可能在意外或在测试环境中运行良好,然后在生产中失败。
-
这可能是我的例子,我正在发送消息
-
@JeroenMostert 即使客户端请求 4 个字节并且服务器在不同的数据包中发送 2 和 2,客户端也会等到他读取 4 个字节。
标签: c# tcpclient tcplistener networkstream