我是否可以使用一个设置来防止将多个TCP数据包合并到Socket.BeginReceive
回调内的单个缓冲区中?
你的下意识反应是我无法阻止TCP分裂/合并数据,但这不是我要求的;我可以清楚地看到在Wireshark中收到的各个数据包,我唯一关心的是延迟,即一旦到达就处理该段。这并不意味着我不知道如何处理拆分/合并段,但这意味着我想避免延迟。
我的代码如下所示:
void WaitForData(ISocketInfo soc)
{
if (socket != null && socket.Connected)
socket.BeginReceive(buffer, 0, buffer.Length,
SocketFlags.None, OnPacketReceived, socket);
}
void OnPacketReceived(IAsyncResult asyn)
{
try
{
var socket = (ISocketInfo)asyn.AsyncState;
numberOfBytesReceived = socket.EndReceive(asyn);
if (numberOfBytesReceived > 0)
{
_queue.Enqueue(buffer, 0, numberOfBytesReceived);
OnNewDataReceived();
}
WaitForData(socketInfo);
}
catch (SocketException ex)
{
Log.Warn("Socket error while receiving packet", ex);
Close();
}
}
当我在WireShark中检查这些数据包时,我可以看到每50ms接收一个TCP数据包,每个数据包(比如说)100个字节。但有时在我的应用程序中有一个100毫秒的延迟,OnPacketReceived
方法获得200个字节。
由于WireShark确认这不是操作系统/网络问题,这可能是什么问题? OnPacketReceived
只是在后台线程上触发,因此它不会阻止该方法,并且程序实际上并没有消耗太多的CPU。
(适用更新)
似乎我没有清楚地表达我的问题。如果数据跨段分割,我的问题不是如何解析数据。我的协议定义得很好(即START_COOKIE,LENGTH,DATA,CRC),我收到数据后立即将数据排入字节FIFO(上面代码片段内的_queue.Enqueue
调用),这样我就可以轻松解析它是异步的。
问题是,如果我看到数据包没有。 Wireshark中的1(100字节)+ 50ms,数据包号码。 Wireshark中的2(100字节)+ 100ms,我的应用程序没有阻塞OnPacketReceived
方法而且没有CPU,为什么.NET每隔一段时间就会调用OnPacketReceived
+ 100ms并将两个数据包合并为一个?
答案 0 :(得分:1)
您可能会收到更少或更多,不能保证您将收到确切的发送内容。
来自MSDN:
无法保证您发送的数据会立即显示在网络上。为了提高网络效率,底层系统可能会延迟传输,直到收集到大量的传出数据。成功完成BeginSend方法意味着底层系统有空间缓冲数据以进行网络发送。
Here是一篇很好的文章,可以解释这一点,以及如何解决问题。
答案 1 :(得分:0)
TCP是一个连续的数据流(它的主要特征是,似乎根本没有数据包,与UDP不同)。因此,由您的软件来定义消息格式。你可以:
总而言之,您必须考虑将流拆分为消息。或者在TCP之上使用HTTP,WebSockets或其他消息格式实现。