c - 使用 tcp_nodelay 发送大消息时出现奇怪的延迟

标签 c node.js sockets tcp

我正在编写一个 C 程序,它通过 TCP 连接发送 bash shell 的输出。为了使我的程序响应更快,我使用setsockopt()来启用TCP_NODELAY,这会禁用Nagle的缓冲算法。这非常有效,除了大消息很少出现延迟之外。例如,如果消息超过 500 字节左右(可能是 512)。前 500 个字节将通过(在小消息中快速),然后在一次性接收其余字节之前将有 1-2 秒的延迟。这种情况只会在每 10-15 次收到大消息时发生一次。在服务器端,消息一次一个字节地写入套接字,并且所有字节都可用,因此这种行为对我来说是意外的。

我最好的猜测是套接字中某个地方有一个 512 字节的缓冲区导致了阻塞?我做了一些时间测试来查看滞后在哪里,我很确定是套接字本身发生了滞后。服务器端的所有数据都无阻塞地写入,但客户端在延迟后收到消息结束。不过,我使用 getsockopt() 来查找套接字的接收和发送缓冲区,它们远远超过 512 字节 - 分别为 66000 和 130000。在客户端,我使用 Express js 在处理程序中接收数据(app.on('data', function(){}))。但我读到这个express函数不缓冲数据?

有人能猜出为什么会发生这种情况吗?谢谢!

最佳答案

由于 TCP_NODELAY 意味着尽快将每段数据作为数据包发送,而不将数据组合在一起,因此听起来您正在发送大量数据包。由于您一次写入一个字节,因此它可以发送仅包含一个字节有效负载和一个更大的帧的数据包。这在大多数情况下都可以正常工作,但一旦第一个数据包由于某种原因丢失,接收方就需要在 TCP 套接字上进入纠错模式,以请求重新传输丢失的数据包。这将导致至少一次甚至多次往返延迟。听起来你对前几百个数据包(值(value) 500 个字节)很幸运,然后通常会遇到第一个数据包丢失,并由于纠错而减慢速度。一种简单的解决方案可能是写入更大的 block ,例如一次写入 10 个字节,而不是 1 个字节,这样丢弃数据包的机会就会少得多。那么您可能会像只处理 5000 字节左右的消息时一样频繁地看到此问题。一般来说,设置 TCP_NODELAY 会导致事情一开始进展得更快,但最终会更快地到达第一个丢弃的数据包,因为 TCP_NODELAY 不会减少每单位数据量发送的数据包数量。因此,它会增加或保持数据包数量不变,这意味着在一定数据量内遇到丢弃数据包的机会将会增加。这里需要在交互感觉和第一次打嗝之间进行权衡。通过避免 TCP_NODELAY,您可以延迟在第一次错误重传发生之前发送的典型数据量。

关于c - 使用 tcp_nodelay 发送大消息时出现奇怪的延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31323509/

相关文章:

node.js - 为什么我不能在 Rasspian OS 中运行相同的应用程序?

node.js - 为什么我的 node.js/socket.io 应用无法在 iOS6 上运行?

c - 将多个 IP 地址匹配到一个端点

java - 如何使用Socket将图片从PC发送到Android?

sql - 保护纯文本文件中敏感数据的最佳实践?

c - 悬挂指针..在一本书中?

c++ - 大型矩阵上的 cblas_dgemm 段错误

javascript - 使用纯npm脚本创建vendor.js包

c# - 适用于 Windows 和 Linux 的同一台机器上的套接字

c - 尝试使用 strtok() 作为 C 中的 shell 函数