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