问题标签 [nagle]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
2150 浏览

c# - 如何在 ServiceStack 中禁用 Nagle 算法?

我们正在使用 ServiceStack 3.9.71.0,我们目前在通过 WAN 连接的客户端遇到无法解释的延迟问题。

200ms+ 后收到带有非常小的有效负载(<100 字节)的回复。

由于地理距离,链路上的往返时间 (RTT) 约为 40 毫秒。这已通过 ping 另一台主机并使用简单的回显服务来测试 TCP 连接的延迟来验证。

ping 和 echo 测试均显示符合预期的延迟。从我们的 ServiceStack 主机获得回复的时间比预期的要长得多。

我们已经验证:

  • WAN 链接仅以 25% 的容量运行(无拥塞)
  • WAN 链路上没有使用 QOS
  • 同一主机快速回复来自本地网络上不同主机的相同请求
  • 延迟不是由我们的代码处理请求引起的

我们现在偶然发现了 Nagle 的算法,它可能意味着 WAN 网络上的小请求的延迟 ( http://blogs.msdn.com/b/windowsazurestorage/archive/2010/06/25/nagle-s-algorithm-is -not-friendly-towards-small-requests.aspx)。

在 .NET 中,可以通过设置TcpClient.NoDelay = truehttps://msdn.microsoft.com/en-us/en-US/library/system.net.sockets.tcpclient.nodelay(v=vs.110).aspx)禁用它。

如何禁用 ServiceStack 的 TCP 处理?

编辑:我不认为这是HttpWebRequest is slow with chunked data的副本。提到的问题涵盖HttpWebRequest了 ServiceStack 不使用的问题。ServiceStack 使用HttpListener也恰好由上述ServicePointManager. 我们将进行测试,看看设置是否能ServicePointManager.UseNagleAlgorithm = false解决问题。

0 投票
1 回答
1054 浏览

sockets - 将 TCP_QUICKACK 与 nginx 一起使用

我最近被服务器端的延迟 ACK 和客户端的 Nagle 算法相结合,产生了可识别的 40 毫秒延迟,此处记录:http: //www.boundary.com/blog/2012/ 05/知道-a-delay-nagles-algorithm-and-you/

解决此问题的最简单方法是在客户端使用 TCP_NODELAY(或者 TCP_CORK 在我们的情况下也应该工作)。但是,我无法直接控制客户端,并想尝试服务器端修复。似乎 TCP_QUICKACK 选项在这里可以解决问题,因为服务器会立即 ACK,从而导致客户端的 Nagle 算法立即发送下一个数据包。

令人惊讶的是,我找不到任何关于以前尝试过这个的人的参考。这是一个坏主意吗(除了我们将发送更多,可能是免费的 ACK 的事实)?由于看起来这个选项不能通过任何 nginx 配置获得,因此最好直接修补 nginx(可能在http://hg.nginx.org/nginx/file/dcae651b2a0c/src/http/ngx_http_request 附近)。 c#l3025 )?

谢谢!

0 投票
1 回答
1225 浏览

c# - C# 服务器 - TCP/IP 套接字效率

美好的一天!

我正在为一个封闭源代码的游戏开发一个开源服务器 - 游戏使用 TCP/IP 套接字(而不是 UDP,doh ......)所以作为一个基于连接的协议,我被限制使用这个。

我当前的程序结构(简化):

核心线程

  • 接收新连接并创建一个新的客户端对象。

客户对象

  • IOloop(在自己的线程上运行)

    • 从套接字获取数据,处理数据包。(一次一包)
    • 发送从其他线程缓冲的数据(一次一个数据包)

当它是自己的线程时,客户端将立即(无延迟)发送数据。


我注意到程序有一个巨大的缺陷,主要是它发送数据的速度非常慢。因为我是一个包一个包地同步发送数据。(Socket.Send(byte[] 缓冲区))

我想几乎立即发送数据,没有延迟 - 异步。

每次我想发送一个数据包时,我都尝试创建一个新线程(因此每个数据包都在它自己的托管线程上发送),但这是一个巨大的混乱。

我当前的系统使用禁用 nagle 算法的同步发送 - 但这有瓶颈的缺陷 - 发送一个数据包,发送操作块直到 TCP 确认,然后发送下一个......我可以每 100 毫秒轻松发出 10 个数据包,如果数据包需要 400 毫秒才能发送,这会备份并中断。当然,在我的本地主机上,我没有遇到这个问题。


所以,我的问题是:发送多个小数据包的最佳方式是什么?我正在考虑将要在每个 IO 线程循环结束时发送的数据合并到一个大字节缓冲区,以减少来回延迟 - 但这里明显的问题是这破坏了我希望停止的 nagle 算法避免延误。

同步发送如何工作?在我相信的接收方确认正确接收到数据之前,它会阻塞吗?有没有办法可以在不等待确认的情况下做到这一点?我确实理解数据包必须全部按顺序正确(根据协议规范)。

0 投票
0 回答
213 浏览

c# - TCP NO_DELAY + 丢失报头 + TCP 重传

在这种情况下看到了一个奇怪的情况:

  1. 发送 HTTP 请求时带有 TCP 标志 NO_DELAY(即禁用 Nagle 算法);
  2. WireShark 不捕获带有 HTTP 动词和标头的 TCP 数据包 - 仅看到带有 HTTP 正文的数据包(数据包丢失了吗?);
  3. 带有 ACK 的远程主机响应表明并非所有数据都得到确认;
  4. 发生 TCP 重新传输,现在 WireShark 捕获 HTTP 动词和标头。

来自 WireShark 的 TCP 流

更多注释:

  1. 如果 Nagle 算法为 ON,则看不到数据包丢失或重新传输;
  2. 该问题在两个不同的网络中得到验证,因此该问题几乎与网络环境无关(除了主机是虚拟机这一事实);
  3. 使用 c# HttpClient (.NET 4) 发出请求;
  4. HTTP 正文大小似乎起作用 - 对于相对较小的数据包没有问题。

因此,看起来 NO_DELAY 会导致 TCP 数据包丢失且内部带有 HTTP 标头/动词的奇怪行为。

有什么建议吗?

0 投票
1 回答
865 浏览

javascript - 禁用 Nagle 的算法客户端/JavaScript

Nagle 算法是否也需要禁用客户端?如果是这种情况,我还没有找到单独通过 JavaScript 禁用 Nagle 算法的方法。

我正在尝试从托管在 Raspbian OS 上的 PHP CLI 服务器(也托管在 Windows 7 和 Ubuntu 上,结果相同)通过 websocket 流式传输数据。此服务器已成功创建套接字并接受多个连接,并已设置 TCP_NODELAY 标志(仅使用 socket_get_option 验证)。

在大多数平台上,无论是否设置了这个 TCP_NODELAY 标志,数据都会流式传输而不会聚集。但是,在Windows 7 Chrome 和 Firefox 上,数据以块的形式到达(有 0.2 秒的延迟)。在Windows 8、Linux、iOS 和 Windows 7 的 Internet Explorer 11 上:我根本看不到这个问题

http://www.13willows.com/hovelme/script/serverControl.php 这里是测试网站,点击“连接”,然后点击“查看游戏”,你应该会看到一个 Current Packet 从 1 到 20,每 50 毫秒稳步递增. 但是,在某些客户端上,它大约每 200 毫秒一次跳跃 4 次。

有什么想法可以阻止这种情况吗?使用 node.js / socket.io 会修复这样的问题,并且仍然允许我从用户的浏览器运行代码吗?

0 投票
0 回答
937 浏览

ios - 如何在 iOS 中禁用 nagle 的算法?

我正在使用 cfwritestream 读取和写入 iOS 的套接字。我需要禁用 Nagle 的算法以提高套接字的写入效率,并进行了更改以包含 TCP_NODELAY,但是,从 pcap 日志中我没有看到 Nagle 的算法已被禁用。

以下是我为套接字启用 tcp_nodelay 选项的代码。这是在调用 wrapsocket 以将本机套接字包装到 cfsocketstream 时完成的。

如果我遗漏了什么,请告诉我。

0 投票
0 回答
587 浏览

php - php回显字符串太长

我不确定这是 php 错误还是服务器配置,但我似乎无法回显长度超过 2,000,000 个字符的字符串。页面只是挂起。

这适用于我的本地机器,但不适用于我的实时服务器。

我尝试使用 str_split 将字符串分解为一个数组并单独输出每个部分,但它仍然不会这样做。

我还看到一些关于这与 Nagle 的算法和 TCP/IP 缓冲有关的评论,但我仍然不知道。

请帮忙!

0 投票
1 回答
246 浏览

algorithm - Nagle 算法、ACK 延迟和 Rlogin 回显

我也被建议在这里问,因为有关协议的具体问题是主题,但如果有人感兴趣,这个问题也对ServerFault有一点悬念。

我正在阅读有关 TCP 数据流、延迟 ACKNagle's Algorithm 的信息。

到目前为止,我明白:

  1. TCP 上的延迟 ACK实现会在接收到的段的确认上产生延迟,以使应用程序有机会在确认的同时写入一些数据,从而避免发送空 ACK 数据包并导致网络拥塞。
  2. Nagle 的算法实现声明您不能发送一个小的 TCP 段,而另一个小段仍然未被确认。这避免了流量被加载了几个tinygram

在某些交互式应用程序上,例如 Rlogin,Nagle 的算法延迟 ACK可能会“冲突”:

当我们键入键盘输入时,Rlogin 会将键盘输入发送到服务器,并且某些键(如F1)会生成一个以上的字节(F1 = Escape + 左括号 + M)。如果这些字节被一一传送到 TCP,它们可以在不同的段中发送。

服务器在获得整个序列之前不会回复回显,因此所有 ACK 都会被延迟(期望来自应用程序的一些数据)。另一方面,客户端会在发送下一个字节之前等待第一个字节确认(尊重Nagle 算法)。这种组合最终导致“滞后”的 Rlogin。

tcpdump在 Rlogin 上发送的F1F2如下所示:

现在的疑问:即使我阅读的页面指出服务器在获得整个密钥序列之前没有回复回显,但通过捕获的数据包tcpdump显示密钥正在各自的 ACK 上回显(第一个回复是 2字节长,因为ESC的回显是两个字符 - 插入符号 + 左括号)。

如果数据正在从应用程序发送到 TCP(回显响应),为什么 ACK 会延迟?根据所陈述的,关于服务器在回显之前等待完整序列,ACK 不应该不包含直到最后一个 ACK​​ 的回显,这将包含整个序列回显?

编辑: 这是tcpdump修改后的 Rlogin 的输出,没有 Nagle 算法(TCP_NODELAY 标志):

可以注意到在第 4 段,延迟约为 0.2 毫秒,即使 Nagle 的算法已关闭(因此所有特殊密钥字节一起到达并且可以一起处理)。在第 6 段,我们无法识别约 0.2 毫秒的延迟,因为服务器需要一段时间来重新处理和重新打包一些丢失段的重传,但这个延迟超过 2 秒。

F2键示例中,在第 11 段,我们还可以注意到约 0.2 毫秒的延迟。我们无法在第 12 段识别它,因为它可能是在第 11 段之后发送的。

这确实表明@MattTimmersans 的答案是正确的,这可能是这本书对段延迟的误解。它们确实可能是网络介质的一个特征,而不是因为数据未向下发送到 TCP 堆栈而延迟 ACK。

参考: http: //people.na.infn.it/~garufi/didattica/CorsoAcq/Trasp/Lezione9/tcpip_ill/tcp_int.htm

0 投票
0 回答
350 浏览

c - Nagle 算法和 SO_SNDBUF

我试图了解使用Nagle's algorithm不同send buffer size值的后果。

我目前的理解send buffer是,它指的是内存的一部分,其中存储了未确认的发送数据包的副本。一旦收到该数据包的 ACK,send buffer就会清除 ACK。如果没有收到 ACK,则从send buffer. 如果我错了,请纠正我。

现在我的问题 -

  1. 如果send buffer已满,这是否意味着即使禁用 Nagle 也不会向接收方发送新数据包?
  2. 如果我将 设置send buffer size为 0 并禁用 Nagle 会发生什么?如果 ACK 永远不会到达,我是否会失去重新发送丢失数据包的能力?
0 投票
0 回答
163 浏览

nagle - 接收端的 Nagle 算法

我想我理解(但我可能错了;-))发送方Nagle算法的原理:只要前一个数据包未被确认,发送方的IP堆栈就可以延迟消息。

然而,如果发送单个数据包并包含多个应用消息(例如 Mn、Mn+1、Mn+2),接收方如何能够将不同的应用消息(Mn、Mn+1、Mn+2)从这个单包?

数据包中是否有任何标志来警告接收者?它与PSH标志有关吗?它与序列号或确认号有关吗?(我不这么认为)

谁负责在接收方拆分消息?IP 堆栈或应用程序?我认为它是 IP 堆栈,但是否有标准选项可以激活?

发送者和接收者应该发送一个共同的配置吗?(例如围绕 NO_DELAY 选项的停用?)

非常感谢您的支持。