简而言之:服务器调用 ::send() 成功,但数据没有通过电缆输出。客户端在几秒钟后发送它的退出命令,因为它没有收到任何东西并且该命令被服务器正确接收。
详细说明:服务器每 1/10 秒向其客户端发送一条命令,每秒发送一次心跳。客户端只为心跳返回一个 ack。我们修改了服务器应用程序以记录发送和接收的每个命令,并且我们使用 Wireshark 记录了 pc 的流量。我们可以将每个记录的命令与一个 TCP 数据包匹配,直到问题出现。问题一次只影响一个客户端。数据继续与其他客户端正常流动。连接通常会在遇到麻烦前几分钟工作。从客户端启动到关闭(即几天),连接应该可以工作。
出现问题时,日志文件包含预期的命令,但 Wireshark 转储中不包含任何内容。下图显示了一个客户端的流量。红线是流量停止时,但服务器继续调用 ::send() 成功。大约 4 秒后,客户端超时并关闭连接。它发送一个退出命令,服务器正常接收。
更让我困惑的是包含退出命令的数据包没有被 TCP ACK 数据包确认。就好像 TCP 连接在发送端完全阻塞了一样。重传是这种堵塞的结果,但即使是建立新连接的 TCP SYN 也没有得到正确处理,也没有得到简单的 TCP ACK。
大约 30 秒后,问题消失,SYN 数据包最终被接受,通信继续使用新连接。
这已在各种 Windows 版本上进行了测试。在测试期间,使用了远程桌面会话,并且从未因同样的问题而断开连接。它保持连接数小时没有任何问题。当客户端通过无线网桥时,问题更加频繁。我们在无线端点的两侧都使用了 Wireshark,我们没有看到可以解释更高断开率的重传或丢包。
当许多客户端连接到同一个网桥时,它们不会同时发生故障。一次只有一个。所以无线噪音似乎不是一个解释。我们可以在 Wireshark 转储中看到一些重传,但通信照常继续,在问题发生之前没有重传。接入点连接到服务器的交换机。客户端电脑和服务器电脑不使用无线网卡。
一直以来,我们一直认为偶尔断线是网络造成的,但现在越来越多的安装是无线的,而且断线频繁到给用户带来困扰。
我们尝试了启用和不启用 Windows 防火墙。即使防火墙被禁用,我们也添加了端口例外。客户端或服务器都没有防病毒软件。