什么可以导致TCP / IP丢弃数据包而不丢弃连接?

我有一个基于Web的应用程序和一个客户端,都是用Java编写的。 对于它的价值,客户端和服务器都在Windows上。 客户端通过Apache HttpClient发出HTTP GET。 服务器阻塞最多一分钟,如果在该分钟内没有消息到达客户端,则服务器返回HTTP 204 No Content。 否则,只要为客户端准备好消息,就会返回HTTP 200正文的正文。

这让我感到困惑:间歇性地为特定的客户端子集 – 总是客户端具有明显不稳定的网络连接 – 客户端发出GET,服务器接收并处理GET,但客户端永远坐着。 启用客户端的调试日志,我看到HttpClient仍在等待响应的第一行。

服务器上没有抛出exception,至少没有任何记录,不是由Tomcat,而是由我的webapp。 根据调试日志,服务器成功响应客户端的每一个迹象都表明。 但是,客户没有显示收到任何东西的迹象。 客户端无限期挂起在HttpClient.executeMethod中 。 在会话超时并且客户端采取导致另一个线程发出HTTP POST的操作后,这变得很明显。 当然,POST失败,因为会话已过期。 在某些情况下,会话到期和客户端发出POST并发现此事实之间已经过了几个小时 。 在整个时间里, executeMethod仍在等待HTTP响应行。

当我使用WireShark查看线路级别的实际情况时,不会发生此故障。 也就是说,对于特定客户端,这种故障将在几个小时内发生,但是当WireShark在两端运行时,这些相同的客户端将在一夜之间运行14小时,而不会出现故障。

还有其他人遇到过这样的事吗? 世界上有什么可以导致它? 我认为即使在短期网络故障中,TCP / IP也可以保证数据包传输。 如果我设置SO_TIMEOUT并在超时后立即重试请求,则重试始终成功。 (当然,我首先中止超时请求并释放连接以确保将使用新的套接字。)

思考? 想法? 是否有一些TCP / IP设置可用于Java或Windows中的注册表设置,以便在丢失的数据包上启用更积极的TCP / IP重试?

您是否完全确定服务器已成功将响应发送到似乎失败的客户端? 我的意思是服务器发送了响应,客户端已经将响应发送回服务器。 你应该在服务器端使用wireshark看到这个。 如果您确定在服务器端发生了这种情况并且客户端仍然没有看到任何内容,则需要从服务器进一步查看链。 是否涉及代理/反向代理服务器或NAT?

TCP传输被认为是一种可靠的协议,但它不保证传输。 您的操作系统的TCP / IP堆栈将非常难以使用TCP重新传输将数据包传输到另一端。 如果发生这种情况,你应该在服务器端的wireshark中看到这些。 如果您看到过多的TCP重新传输,则通常是网络基础结构问题 – 即错误或配置错误的硬件/接口。 TCP重传对于短暂的网络中断非常有效,但在具有较长中断的网络上表现不佳。 这是因为TCP / IP堆栈仅在计时器到期后才发送重传。 在每次不成功的重传之后,该计时器通常会加倍。 这是为了避免因重传而泛滥已经存在问题的网络。 正如您可能想象的那样,这通常会导致应用程序出现各种超时问题。

根据您的网络拓扑,您可能还需要将探测/ wireshark / tcpdump放置在网络中的其他中间位置。 这可能需要一些时间来找出数据包的去向。

如果我是你,我将继续使用wireshark进行监控,直到问题再次发生。 它很可能会。 但是,听起来你最终会发现的就是你已经提到的 – 片状硬件。 如果修复片状硬件是不可能的,您可能需要构建额外的应用程序级别超时和重试以尝试在软件中处理该问题。 听起来你开始走这条路了。

忘记刷新或关闭主机侧的sockets可能会间歇性地产生这种效果,这取决于可能受到任何监视机制存在影响的时间的短响应。

特别是忘记关闭会让sockets悬空,直到GC绕过它来回收它并调用finalize()。

如果您正在使用长时间运行的GET,那么您应该在客户端以服务器超时的两倍超时,如您所发现的那样。

在客户端发送消息并期望响应的TCP上,如果服务器崩溃并重新启动(比如示例),那么客户端仍然在等待套接字从服务器获取响应服务器不再侦听该套接字。

一旦客户端在该套接字上发送更多数据,客户端将只发现服务器端上的套接字已关闭,并且服务器拒绝此新数据,并关闭套接字。

这就是为什么你应该在请求上有客户端超时的原因。

但是,由于您的服务器没有崩溃,如果服务器是multithreading的,并且该客户端的线程套接字已关闭,但是在那个时间(持续时间分钟),客户端发生了连接中断,那么结束套接字会让我丢失,并且因为您没有从客户端向服务器发送更多数据,所以您的客户端再次被搁置。 这将与您的剥落连接观察相关联。

我本身没有见过这个,但是我看到了大型UDP数据报的类似问题,导致IP碎片导致拥塞并最终丢弃以太网帧。 由于这是TCP / IP,我不希望IP碎片成为一个大问题,因为它是基于流的协议。

我要注意的一件事是TCP不保证交付! 它不能。 它保证的是,如果你发送字节A后跟字节B ,那么在收到字节A之前你永远不会收到字节B.

话虽如此,我会将客户机和监控机器连接到集线器。 在监控机器上运行Wireshark,您应该能够看到正在发生的事情。 我确实遇到了与HTTP请求之间的空白处理和不正确的HTTP块大小相关的问题。 这两个问题都是由手写的HTTP堆栈引起的,所以如果你使用的是片状堆栈,这只是一个问题。

这些计算机可能安装了病毒/恶意软件吗? 使用wireshark安装winpcap( http://www.winpcap.org/ )可能会覆盖恶意软件所做的更改(或者恶意软件可能只是检测到它正在被监控而不会尝试任何可疑的东西)。

如果丢失数据,很可能是由于读取或写入库中的软件错误。