【问题标题】:Windows TCP Handshake ProblemWindows TCP 握手问题
【发布时间】:2011-05-01 07:20:32
【问题描述】:

我正在尝试创建从嵌入式控制器到 Windows Vista 服务器的 TCP 连接。我正在编写应用程序的 Windows 服务器部分。

当控制器尝试连接时,可能需要多次尝试才能建立连接。我已使用 Wireshark 调试问题,但似乎 Windows TCP 堆栈未遵循正确的握手协议。

Wireshark 转储:

"No","Time","Source","Destination","Protocol","Info"

尝试1:

"39","9.025322","10.0.0.252","10.0.0.92","TCP","49153 > xinuexpansion4 [SYN] Seq=0 Win=127 Len=0"
"40","9.025377","10.0.0.92","10.0.0.252","TCP","xinuexpansion4 > 49153 [ACK] Seq=1 Ack=1 Win=2048 Len=0"
"47","10.031750","10.0.0.252","10.0.0.92","TCP","49153 > xinuexpansion4 [RST] Seq=0 Win=127 Len=0"

尝试2:

"55","12.193941","10.0.0.252","10.0.0.92","TCP","49154 > xinuexpansion4 [SYN] Seq=0 Win=127 Len=0"
"56","12.194045","10.0.0.92","10.0.0.252","TCP","xinuexpansion4 > 49154 [ACK] Seq=1 Ack=1 Win=2048 Len=0"
"57","13.200431","10.0.0.252","10.0.0.92","TCP","49154 > xinuexpansion4 [RST] Seq=0 Win=127 Len=0"

尝试 3:

"67","18.529871","10.0.0.252","10.0.0.92","TCP","49156 > xinuexpansion4 [SYN] Seq=0 Win=127 Len=0"
"68","18.529957","10.0.0.92","10.0.0.252","TCP","xinuexpansion4 > 49156 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1460"
"69","18.536318","10.0.0.252","10.0.0.92","TCP","49156 > xinuexpansion4 [ACK] Seq=1 Ack=1 Win=127 Len=0"

10.0.0.252 是发起连接的控制器,10.0.0.92 是 Windows PC。

据我了解,正确的顺序是 SYN、SYN+ACK、SYN。我大部分时间得到的是 SYN、ACK、RST(即 Windows 用 ACK 而不是 SYN+ACK 响应)。在上面的转储中,它显示了 3 次连接尝试,第 3 次有效。

我可以做些什么来“修复”Windows 以使其正确响应?

编辑 - 2 个数据包捕获

【问题讨论】:

    标签: windows windows-vista tcp


    【解决方案1】:

    我查看了您的 pcap 文件,我能看到的唯一区别是:

    (1) Windows 客户端在其 SYN 数据包中发送“看似随机”的初始序列号,而嵌入式客户端在其 SYN 数据包中发送初始序列号,如 1、2、3。只要服务器绝对没有(源 IP、源端口、目标 IP、目标端口)4 元组的 TCP 连接状态,我知道这不会有任何区别,但我想提一下以防万一它可以帮助您或其他人想到一个想法。

    (2) Windows 客户端发送带有 TCP 选项的 SYN 数据包,而嵌入式客户端发送没有 TCP 选项的 SYN 数据包。同样,据我所知,这不应该导致您所看到的行为,而且,也许它会为其他人敲响警钟。

    如果您想查看数据包头及其解码的更多详细信息,我推荐 tshark,它作为 wireshark 包的一部分提供。您可以使用这样的命令行获取大量详细信息:

    tshark -n -V -x -r Embeded-4-attempts.pcap > Embeded-4-attempts.txt

    关于您在上面所做的“需要再尝试 1 次连接”观察,我会指出客户端需要 1 多时间才能达到 Windows Vista 服务器尚未看到的新初始序列号,因为我敢打赌,每次重新启动客户端时,它都会再次发送一个序列号为 1 的 SYN 数据包,然后在下一次连接尝试时发送 2,然后是 3,依此类推。Windows Vista 服务器可能正在等待查看正确响应连接之前的新初始序列号。

    嗯。现在我想起来了,也许问题是 Vista 服务器没有正确响应来自客户端的 RST 数据包?如果是这样,服务器认为所有这些客户端连接仍然处于活动状态,而客户端没有与之关联的状态。服务器用 ACK 响应它仍然具有状态的连接尝试,而不是 SYN-ACK,因为它仍然具有它们的状态。客户端没有它们的状态,并且表现得好像它们是新连接。重新启动客户端会使其重新尝试与上次启动时相同的 TCP 源端口和初始序列号,因为它的简单 TCP 堆栈不会像 Windows 客户端那样随机化这些值。

    无论如何,值得深思。如果您可以访问简单 TCP 客户端的源代码,请查看是否可以使其在发出新连接请求时使用随机源端口和初始序列号。

    【讨论】:

    • 安迪,我认为你正在做某事。我已将服务器代码更改为更积极地关闭“丢失”的套接字连接。现在,客户端第一次或第二次连接。看起来 Vista 正在缓存连接,只是假设客户端想要重置消息编号。我正在开发客户端软件,因此经常重新启动嵌入式控制器并因此重置消息编号。非常感谢您的帮助。保罗
    【解决方案2】:

    您是否尝试过使用 telnet 从运行完整操作系统(如 Windows 或 Linux)的客户端连接到您的 Vista 服务器?在 Linux 上,您至少可以在命令行上指定一个 TCP 端口号来连接,并查看它是否可以连接到您的 Vista 服务器。

    一种检查方法:Vista 服务器是否运行某种防火墙来阻止连接发生?

    【讨论】:

    • 没有防火墙。我有一个非常简单的客户端程序,每次都第一次连接。日志显示,对于 Windows 客户端,服务器使用 SYN+ACK 进行响应。对于嵌入式客户端,可能需要多次尝试才能获得 SYN+ACK。
    【解决方案3】:

    当握手失败时,这确实遵循协议。作为协议的一部分,允许 RST 重置连接。问题是,为什么会发生重置?两台机器之间是否有系统,正在发送重置?如果您在同一系统上同时运行服务器和客户端,您是否仍会重置(这表明您的代码中存在错误)?如果你在不同的操作系统上运行服务器,在与 Windows 服务器相同的网络插孔中,你会看到 RST 吗?

    【讨论】:

    • 客户端和服务器之间除了一个非管理型交换机外没有任何东西。客户端是嵌入式处理器(螺旋桨芯片),因此无法在 Windows 下运行。 RST 是允许的,但它是为了响应一个不正确的 ACK 应该是 SYN+ACK,所以它的服务器失败了。
    • 在XP下运行服务器程序,每次尝试都是第一次连接。
    • 该协议允许服务器的 SYN 和 ACK 数据包单独或一起发送,尽管大多数实现将两者一起发送。您是在编写自己的 TCP 堆栈,还是在使用嵌入式处理器的实现?您可以在模拟器中运行您的客户端吗?如果它在模拟器而不是硬件中工作,则表明两者之一存在错误......
    • 我现在完全糊涂了。我在 Windows 中编写了一个简单的客户端程序来连接。每次,服务器 prog 都会响应 SYN+ACK。我还发现了嵌入式 proc 的模式。每次我在不重新启动服务器的情况下重新启动客户端时,都需要再尝试 1 次连接(即第一次重新启动需要 2 次尝试连接,第 2 次重新启动需要 3 次尝试等)。我正在使用我有代码的免费可用的 TCP 堆栈,但我觉得 Vista 中有一些奇怪的功能来确定如何响应我找不到任何信息的第一个 SYN 数据包。跨度>
    • 这也可能与您在嵌入式设备上使用的 TCP 堆栈有关 - 前两个 SYN 和第三个 SYN 之间可能有所不同。您可以将完整的数据包捕获添加到您的问题中吗?此外,您是否在嵌入式设备和其他应用程序中看到了同样的行为?
    猜你喜欢
    • 2011-07-02
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多