RST 上的 TCP 重传 - Windows 和 Linux 上的套接字行为不同?

Tre*_*yan 4 sockets tcp raspberry-pi .net-core

概括:

猜测这里的问题与 Windows 和 Linux 如何处理 TCP 连接或套接字有关,但我不知道它是什么。我正在启动与其他人开发的定制硬件的 TCP 连接,并且我正在尝试了解其行为。为此,我创建了一个 .Net core 2.2 应用程序;在Windows系统上运行,我可以成功启动连接,但在Linux(最新的Raspbian)上,我不能。

看来这可能是因为 Linux 系统不会在 RST 之后尝试重试/重新传输 SYN,而 Windows 系统会这样做 - 而且这种行为似乎是这个特殊硬件工作原理的关键。

背景:

我们有一个黑匣子硬件,可以使用制造商提供的 Windows 应用程序通过网络进行控制和查询。数据未加密,无需身份验证即可连接,并且应用程序还存在一些其他问题。最终,我们希望能够将数据从它中继到另一个系统,因此我们决定制作自己的应用程序。

我花了相当长的时间试图理解数据包格式,并创建了一个针对 .net core 2.2 的库,可用于与该套件成功通信。在这样做时,我发现该设备似乎需要通过 UDP 发送一种“请求连接”命令。之后,我就能够在端口 16000 上启动 TCP 连接,尽管第一次 TCP 尝试总是会返回 RST、ACK - 因此需要进行第二次尝试。

我开发的东西在 Windows (x86) 和 Linux (Raspberry Pi/ARM) 系统上都运行得非常好,并且我可以发送和接收数据。但是,在Raspbian系统上运行时,发起TCP连接时似乎出现问题。我可以发誓,我们让它在以前的版本中工作得绝对正常,但以前的提交似乎都不起作用 - 所以它很可能是系统/内核更新改变了一些东西。

问题:

当启动与该设备的 TCP 连接时,它将立即重置连接。即使使用制造商提供的软件,它也会立即重新尝试连接并成功;因此,这种重置一次然后第二次起作用的行为本身并不是我可以控制的“问题”。

我想要理解的是为什么 Windows 系统会立即通过重传重新尝试连接...... 在此输入图像描述

..但是Linux系统在一次尝试后就放弃了(这是数据包捕获的结束..) 在此输入图像描述

为了证明这不是特定于应用程序的问题,我尝试在 Windows 系统和 Raspbian 系统上使用 ncat/netcat,以及在单独的笔记本电脑上使用 Kali 系统来证明这不是 ARM/Raspberry 问题。由于 UDP“请求”尚未发送,因此连接永远不会成功,但这只是说明了操作系统之间的不同行为。

Linux 版本看起来与上面几乎相同,它们发送一个被重置的数据包 - 而 Windows 尝试演示了多次重传。

在此输入图像描述

那么,有人对这种行为差异有任何答案吗?我猜这不是 .net core 特定问题,但是有什么方法可以设置套接字选项来尝试重新传输?或者可以使用 systemctl 命令或其他命令在操作系统级别进行设置吗?我确实尝试看看.net中是否有任何SocketOptionNames,看起来它们会控制尝试/重试,因为这个答案让我想知道,但到目前为止还没有运气。

如果有人对如何更好地跨平台调整这种行为有任何建议,或者可以解释这种差异的原因,我将非常感激!

小智 6

不错的发现!根据这个,如果 Windows\xc2\xb4 TCP 在发送 SYN 后收到来自远程主机的 RST/ACK,它将重试连接

\n\n
\n

...在收到来自目标主机的ACK/RST客户端后,客户端确定那里确实没有服务在监听。在 TCP 的 Microsoft Winsock 实现中,待处理的连接将不断尝试发出 SYN 数据包,直到达到最大重试值(在注册表中设置,该值默认为额外 3 次)...

\n
\n\n

根据同一篇文章,用于限制这些重试的值在 HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\TcpMaxConnectRetransmissions 中设置。至少在 Win10 Pro 中,默认情况下似乎不存在\xc2\xb4t。

\n\n

尽管这对于 Windows 机器来说很方便,但应用程序仍然应该确定自己的处理失败连接尝试的标准(IMO)(即尝试次数、超时等)。

\n\n

无论如何,正如我所说,令人惊讶的事实!生活和学习我想...

\n\n

克里斯蒂安.

\n