2013-08-24 42 views
7

我有一个客户端.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回调当数据到达服务器?

-

UPDATE

这已经得到解决。这是因为服务器有一个单一的处理器和单核。加入另一个核心后,问题立即解决。当呼叫通过服务器时,ReadCallback立即被调用。

谢谢你的建议!

+0

您可以轻松编写一个同步接收的小测试程序,只是为了查看它是否以更及时的方式获取数据?这可能有助于隔离问题。 –

+0

我会尽力做到这一点。另一个问题说,这将是同样的结果,但无论如何它可能值得一试。 –

+0

@JimMischel:我将其更改为同步,现在它立即收到数据。所以问题仍然是BeginReceive在数据到达时不会立即回调。我不想继续同步,因为那时我必须自己执行线程来同时处理多个连接。 –

回答

1

由OP的要求,在这里复制我的“评论/答案”。

我的猜测是,问题出现在单核机器上的线程调度。这是一个老问题,在超线程/多核处理器的现代时代几乎消失。当一个线程在程序执行过程中产生时,它需要预定的时间运行。

在单核机器上,如果一个线程继续执行而没有明确地将控制权交给操作系统调度程序(通过等待互斥/信号或通过调用睡眠),执行任何其他线程()优先级较低的)可能会被调度程序无限期地推迟。因此,在所描述的情况下,异步网络线程(最有可能)只是因执行时间而不足 - 只能不时获取片断。

添加第二个CPU /核心,很明显,通过提供一个并行调度环境来解决这个问题。

+0

不,在我的情况下,我有7个核心机器,但是〜15秒后,readcallback被激活。所以我在主线程的工作线程内启动了这个“listener.BeginAccept()”方法。所以现在所花费的时间减少到〜5秒。这是正确的方法吗? – SaddamBinSyed

7

一种方法可能是调整发送端的SO_SNDBUF选项。当服务器/客户端在同一个盒子上时,即使你没有遇到这个问题,由于服务器之间的(可能)较慢的发送速率,有一个小缓冲区可能会限制发送端。如果发送方发送速度不够快,那么发送方缓冲区可能会尽快填满。

更新:我们做了一些调试,结果发现问题是应用程序运行速度较慢。

+0

我将发送缓冲区大小设置为正在发送的消息的大小。如果我把它设置得更高或更低,它会更好吗? –

+0

'byte [] msg = Encoding.ASCII.GetBytes(strMsg); socket.SendBufferSize = msg.Length; socket.Send(msg);' –

+0

SO_SNDBUF与设置msg.Length不同。 SO_SNDBUF表示应用程序下的传输缓冲区,并且基于每个套接字。 msg.Length适用于每个数据包的基础上。基本上,如果SO_SNDBUF很大(让我们说大约20个数据包),那么它不会限制应用程序。否则,发送呼叫可能会阻塞(如果套接字阻塞)。 –

6

这可能是Nagle算法正在发送端等待更多的数据包。如果你发送的是小块数据,它们将被合并为一个,所以你不会为小数据支付巨大的TCP头部开销。 您可以使用以下命令禁用它:StreamSocketControl。NoDelay 请参阅:http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocketcontrol.nodelay

Nagle算法可能被禁用于回送,这是发送方和接收方都在同一台计算机上的原因的可能解释。

+0

听起来很有希望。不幸的是它没有任何区别。我在发送方这样设置:'socket.NoDelay = true;' –

+1

我同意。由于NoDelay在200毫秒的时间刻度下工作,因此不会产生10秒的延迟。这就是我之前没有提出的原因 - 但知道NoDelay不是罪魁祸首是很好的。 –

+0

Gabi,如果您有任何其他建议,我会非常感兴趣的追求他们。 –