我有一个接口,其中线程写入套接字并由远程服务器接收。当线程争用变高时,存在套接字数据乱序的问题。我有一个通过套接字发送的“标准”消息,我可以在字节级看到第二条逻辑消息正在写入第一条逻辑消息的一半。显然这意味着接口因数据损坏而失败。
套接字上使用的唯一特殊设置是
m_socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp,
System.Net.Sockets.SocketOptionName.NoDelay, 1)
m_Socket.Connect(m_remoteServerName, m_remoteServerPort)
我尝试了解锁逻辑消息的简单解决方案,所以我的逻辑是:
lock (sending)
{
msgbytes = GetLogicalMessage();
m_socket.Send(msgbytes, 0, msgbytes.Length, SocketFlags.None);
}
接收方实际上正好相反,从每条逻辑消息中读取消息头后跟消息有效负载。
正在从多个线程访问send方法,但我很难过看。我查看了代码,所有对套接字的访问都是通过锁定方法(接收除外)。除了.Send()不能按我期望的方式工作之外,我看不到任何明显的东西。这是我理解的一个流,所以缓冲区写入需要完成,即使数据在调用结束时没有被推出套接字。
答案 0 :(得分:3)
是的,您对Send
方法的理解不正确 - 它并不保证您提供的所有字节都放在套接字发送缓冲区中。缓冲区可能没有足够的空间,因此您必须注意返回值,即返回的字节数。
通常的技术是循环send
。请注意,内核内TCP / IP堆栈异步地消耗缓冲区,因此下一次调用send
并不一定会再次阻塞。
在线程存在的情况下,这仍然不是很漂亮,因为你会在发送消息时出现任意延迟。
我可能会建议将套接字处理移动到自己的线程中,并通过队列将worker连接到它,这将适应消息传递中的峰值。