我将 tcp 用于非常多的小型发送,我应该关闭 Nagles 算法吗? (人们也将其称为 TCP_NODELAY)
Posted
技术标签:
【中文标题】我将 tcp 用于非常多的小型发送,我应该关闭 Nagles 算法吗? (人们也将其称为 TCP_NODELAY)【英文标题】:I'm using tcp for very many small sends, should I turn off Nagles algorithm? (People also know this as TCP_NODELAY) 【发布时间】:2011-06-01 21:05:04 【问题描述】:我重发了这篇文章,因为我的标题选择太糟糕了,对此感到抱歉。我的新帖子可以在这里找到:After sending a lot, my send() call causes my program to stall completely. How is this possible?
非常感谢大家。问题是客户端实际上是机器人,他们从不从连接中读取。 (感觉很傻)
【问题讨论】:
你可以简单地编辑你的标题,你知道的。 哈哈,我试过了,但我想不通。我更喜欢那个:/。 【参考方案1】:Nagle 不会导致“消失在内核中”,这就是为什么禁用它对您没有帮助。 Nagle 只会缓冲一段时间的数据,但最终会在没有用户提示的情况下发送数据。
还有其他罪魁祸首。
编辑更新的问题。
您必须确保客户端正在接收所有发送的数据,并且它正在快速接收数据。让每个客户端写入日志或进行验证。
例如,如果客户端正在等待服务器接受它的 23 字节更新,那么它可能没有接收到数据。这可能会导致服务器的发送缓冲区被填满,从而导致降级并最终导致死锁。
如果这确实是罪魁祸首,解决方案将是一些异步通信,例如 Boost 的 Asio 库。
【讨论】:
是的,我就是这么想的。不过我真的一无所知。我一直在看的东西可能是 tcp 缓冲区大小......我真的不知道 -_- @returneax 您能否修改您的问题以包含您用于在客户端和服务器上发送/接收数据的代码?我想知道您是否正在做一些导致死锁等的事情。 当然,客户端是用 C# 编写的,我的朋友正在编写它,但现在我可以给你服务器代码。服务器也是多线程的... 多线程是相当简单的。这是两个通过消息队列进行通信的线程。第一个线程只是在端口 3500 上侦听新连接。然后它验证他们的用户名和密码创建一个客户端对象并填写其数据,然后通过消息队列将指向该对象的指针作为字节数组传递。因此,当没有人连接登录线程时,accept() 被阻塞。 @return 我更新了我的答案,但现在我看到 Nikolai 打败了我。【参考方案2】:如果send()
在 TCP 套接字上阻塞,则表明发送缓冲区已满,进而表明连接另一端的对等方读取数据的速度不够快。也许那个客户完全卡住了,没有经常打电话给recv()
。
【讨论】:
【参考方案3】:TCP_NODELAY
可能有助于小数据包从发送方到接收方的延迟,但您给出的描述指向不同的方向。我可以想象以下内容:
SO_SNDBUF
) 并导致服务器进程在 send(2)
系统调用中出现“卡住”。此时内核等待另一端确认一些未完成的数据,但接收方并不期望它,所以它没有recv(2)
。
可能还有其他解释,但不看代码很难说。
【讨论】:
您好 Nikolai,我知道客户从不读取数据这一事实。客户端正在由另一个程序模拟。如果他们从不接收数据会导致我自己的缓冲区溢出吗? 转念一想,看来 UDP 可能更适合您的需求。以上是关于我将 tcp 用于非常多的小型发送,我应该关闭 Nagles 算法吗? (人们也将其称为 TCP_NODELAY)的主要内容,如果未能解决你的问题,请参考以下文章