为啥 Node.js 中的某些 TCP 套接字比大多数其他套接字需要更多的时间来连接?

Posted

技术标签:

【中文标题】为啥 Node.js 中的某些 TCP 套接字比大多数其他套接字需要更多的时间来连接?【英文标题】:Why some TCP sockets in Node.js take much more time to connect than most others?为什么 Node.js 中的某些 TCP 套接字比大多数其他套接字需要更多的时间来连接? 【发布时间】:2021-12-11 09:52:35 【问题描述】:

我创建了小库 tcp-exists 来检查 tcp 端点是否存在。只需遍历网络以在特殊端口上查找任何内容。

code of lib on github

但是当我迭代时——一些 tcp 套接字(由 lib tcp-exists 创建)需要大量时间(1-3 秒而不是 5-20 毫秒)才能在 100% 现有端点上建立连接。

import tcpExists from 'tcp-exists'

async function main () 
  for (let i = 1; i < 250; ++i) 
    let time = performance.now()
    const exists = await tcpExists('192.168.1.87', 80, 2000)
    time = performance.now() - time

    console.log(`time [$i]:`, time)
    if (time > 500) console.log('=====STRANGE=====')
    if (!exists) console.log('exists')
  


main()

在一个 IP 上检查相同端口或不同端口,或者检查不同 IP 之间没有区别。其中一些连接将花费 x100 多倍的时间来建立连接。可能会导致存在端点存在的情况,但由于超时时间很小,该函数将返回false

我无法为一次检查设置大于 25 毫秒的超时。因为如果我想从 192.168.0.0 扫描到 192.168.255.255(65536 个端点)——大部分 IP 没有端点,应该通过超时返回false——并使用例如 1s 作为超时——那么它将需要65536 秒或 ~18 小时...

【问题讨论】:

使用 Wireshark。您可能会发现额外的时间来自主机没有立即回复您。此外,如果您想制作端口扫描器,则不需要完整的 TCP 连接。另见:tripwire.com/state-of-security/featured/… 为什么要连续连接同一个 IP/端口 250 次? @jfriend00 这是一个复制问题的简单示例 【参考方案1】:

TCP 握手意味着客户端向服务器发送一个 SYN,服务器 ACK 客户端 SYN 并返回自己的 SYN(通常都在一个数据包中,即 SYN+ACK),然后客户端对服务器做出反应SYN 与它自己的 ACK。因此,握手的速度取决于客户端和服务器之间的网络延迟以及服务器对连接请求 (SYN) 的反应速度。途中丢失的任何数据包都需要在超时后重新传输,这进一步增加了 TCP 握手的时间。

所有这些都超出了客户端的控制,即无法加快速度。因此,高性能扫描仪不会尝试一个接一个的连接,而是并行尝试多个连接。

【讨论】:

感谢您关于并行连接的建议,我会尝试,但仍然不是答案。我真的很感兴趣为什么会发生这样的事情。为什么某些套接字连接会定期(有时​​每 24 个连接,有时每 75 个连接)需要 x50-x100 次才能连接?那是关于节点套接字的事情,或者它可能取决于操作系统或者它记录在某处? @JerryCauser:与同一主机的连接时间的较大变化通常是由丢包引起的。这种丢失只有在超时后才被检测到,然后重新发送数据包,这大大增加了连接时间。数据包丢失可能是由物理层的故障引起的,尤其是无线连接会受此影响。它可能是由网络过载引起的,例如网络上的某些其他设备发送大量数据,以致路由器/交换机无法跟上所有数据包。这可能是由于接收设备丢弃数据包以限制潜在的攻击。 1) 无线 - 没有。我也用有线连接对其进行了测试——没有任何变化。 2)路由器 - 没有。我在同一台机器上测试过——只是改变了延迟正常连接。 3) 我已经用几个设备 pi4-8gb、macbook、router kingetic ultra、router mikrotik、router tp-link 对其进行了测试。麻烦反复。仅当我尝试检查 8.8.8.8:53 时 - 一切都按预期工作,但请求之间存在约 45 毫秒的延迟,而不是 1-2 毫秒。 @JerryCauser:您当前提供的所有详细信息都与调试您的特定问题相关。他们应该从一开始就在问题中,这样人们就可以提供一个比我给出的更通用的答案。请包括您可能对您的问题有的详细信息和更多详细信息,而不是仅在对通用答案的评论中提供它们。 我会添加有问题的信息,但是您是否尝试过我的代码示例来重现问题?或者只是说“丢包问题”并粘贴有关 TCP 如何工作的信息(我已经知道)?只要您尝试过,那么没有我的 cmets 一切都会变得显而易见。

以上是关于为啥 Node.js 中的某些 TCP 套接字比大多数其他套接字需要更多的时间来连接?的主要内容,如果未能解决你的问题,请参考以下文章

在 node.js 中管理基于命令的 TCP 套接字 API 上的连接

为啥 Node.js 无法连接到套接字时不会抛出错误?

我如何连接到 Node.js 中的星号

多台机器上的 Node.js tcp 套接字服务器

深入浅出Node.js - 网络编程

Node.js TCP 传入消息拆分成包