【发布时间】:2013-01-29 14:11:52
【问题描述】:
我正在用 .Net/C# 编写一些代码,以通过以太网与一些工厂设备进行通信。我首先分配一个处理程序:
_TCPConn.BeginReceive(
_StateObject.sBuffer, 0, _StateObject.sBuffer.Length, SocketFlags.None,
new AsyncCallback(Socket_DataArrival), _StateObject);
然后在我的处理程序中,首先,我执行 EndReceive,然后我将数据从套接字缓冲区传输到我自己的输入缓冲区以便稍后进行进一步处理,我记录一些内容,然后我执行 BeginReceive 以重新启动,然后我退出处理程序。所以...
....
StateObject stateObject = (StateObject)ar.AsyncState;
int bytesReceived = stateObject.sSocket.EndReceive(ar);
// transfer bytes, log stuff, then reenable receive and leave . . .
_TCPConn.BeginReceive( _StateObject.sBuffer, 0,
_StateObject.sBuffer.Length, SocketFlags.None,
new AsyncCallback(Socket_DataArrival), _StateObject);
return;
这在大多数情况下都可以正常工作,但如果工厂设备发送 2 个数据包并拢发送它会失败。这是一个 Wireshark(网络嗅探器)输出。第一列是以微秒为单位的前一个数据包的时间增量(是的,“微”,而不是“毫秒”)
002397 10.1.1.116 10.1.2.11 TCP .... Len=6
000024 10.1.1.116 10.1.2.11 TCP .... Len=9
当这种情况发生时,第一个数据包似乎消失了——处理程序永远不会被调用为 6 字节数据包,只有 9 字节数据包。我知道数据包已经到达 PC,因为 Wireshark 显示了它。
但是,如果我们在工厂设备中引入延迟,那么问题就消失了,而不是 24 微秒,而是 10 毫秒。不幸的是,这不是一个解决方案,因为我们无法改变世界各地工厂的大量已安装设备。
关于如何调试和修复此问题的任何建议? 提前致谢!
【问题讨论】:
-
你能贴出从套接字读取的代码吗?
-
您能否确认如果两个数据包同时到达,您总共没有收到 15 个字节 (9+6)。可以在单个处理程序回调中接收使用套接字的两个单独发送。
-
了解如何解析接收到的数据至关重要。有时套接字可以在内部缓冲接收到的数据,因此您只会收到 1 个回调,其中缓冲区包含两个有效负载 (6+9)
-
@Daniel 其中一些是专有的,但我可能会伪装它。更大的问题是它会使原始帖子更长。如果有需求,我可以将其添加为编辑 - 我试图保持原始帖子简洁而不难以阅读。
-
这里有个概念问题。 TCP 通信模型是连续的字节流,而不是“数据包”序列。是 IP 将流切割成数据包,您的应用程序序列化到流中的“数据包”不一定与您在 Wireshark 中看到的内容相关。你能用 Wireshark 检查 TCP 通信的全部内容,包括 ACK 数据包吗?