我有一个客户端.NET应用程序和一个服务器.NET应用程序,通过套接字连接。
客户端每500毫秒发送一个包含20个左右字符的字符串。
在我的本地开发机器上,这很好用,但是一旦客户端和服务器在两个不同的服务器上,服务器在发送时不会立即收到字符串。客户端仍然发送完美,我已经通过Wireshark证实了这一点。我还确认服务器确实每500毫秒收到一次字符串。
问题是,等待邮件的我的服务器应用程序实际上每20秒左右才会收到一条消息 - 然后它会收到这20秒内的所有内容。
我使用异步套接字,由于某种原因,回调不会每20秒调用一次。
在AcceptCallback
中,它会建立连接并致电BeginReceive
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
这适用于我的本地计算机,但在我的生产服务器上,ReadCallback不会立即发生。
BufferSize设置为1024.我也尝试将其设置为10.一旦调用ReadCallback,它会一次从套接字读取多少数据,但这不是真正的问题。一旦它调用ReadCallback,其余的工作正常。
我正在使用微软Asynchronous Server Socket Example,所以你可以看到我的ReadCallback方法是什么样的。
当数据到达服务器时,如何立即获取BeginReceive回调?
-
更新
这已经解决了。这是因为服务器只有一个处理器和一个核心。添加另一个核心后,问题立即得到解决。现在,当呼叫进入服务器时,立即调用ReadCallback。
谢谢你的建议!!
答案 0 :(得分:7)
一种方法可能是调整发送方的SO_SNDBUF选项。当两个服务器/客户端都在同一个盒子上时,你没有遇到这个问题,由于服务器之间(可能)较慢的发送速率,有一个小缓冲区可能会限制发送端。如果发送方发送的速度不够快,那么发送方缓冲区可能会更快填满。
更新:我们做了一些调试,结果表明问题在于应用程序运行速度较慢。
答案 1 :(得分:6)
可能是Nagle算法正在发送方等待更多数据包。如果要发送小块数据,它们将合并为一个,这样就不会为小数据支付巨大的TCP头开销。 您可以使用以下命令禁用它:StreamSocketControl.NoDelay 请参阅:http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocketcontrol.nodelay
可能会禁用Nagle算法进行环回,这可能解释了当您在同一台计算机上同时拥有发送方和接收方时它的工作原理。
答案 2 :(得分:1)
根据OP的要求,在此重复我的“评论/回答”。
我的猜测是,问题出现是因为单核机器上的线程调度。这是一个老问题,在超线程/多核处理器的现代时代几乎绝迹。在程序执行过程中生成线程时,需要预定的运行时间。
在单核机器上,如果一个线程继续执行而没有明确地将控制传递给OS调度程序(通过等待互斥/信号或通过调用Sleep),则执行任何其他线程(在同一进程中)并且优先级较低)可能会被调度程序无限期推迟。因此,在所描述的情况下,异步网络线程(很可能)只是因为执行时间而挨饿 - 不时只获得片段。
显然,添加第二个CPU /核心通过提供并行调度环境来解决这个问题。