【问题标题】:'Stuck' socket on Windows 8.1Windows 8.1 上的“卡住”套接字
【发布时间】:2013-11-01 03:44:51
【问题描述】:

我最近从 Windows 8 升级到了 Windows 8.1。升级后,我开始遇到与 Java 中的 TCP 套接字相关的问题。

我工作的一个应用程序使用 Java ServerSockets,另一个进程连接到该应用程序以发送数据。多年来一直在许多操作系统和 Java 版本中运行的相当标准的东西。

在 Windows 8.1 下,与这些 ServerSockets 的连接偶尔会“卡住”。这似乎在某种程度上取决于一次通过套接字传输的数据量,但是当一次发送适度的约 1 kB 数据时,它很容易发生。

当套接字“卡住”时,会发生以下情况:

  • 发送端完成发送数据并关闭套接字,进程甚至可以终止。在它看来,数据似乎已经发送成功了。
  • 接收方通常会获取已发送的部分或全部数据。但是,当在套接字的InputStream 上调用read 时,它永远不会获得已达到 EOF 的“-1”指示符。相反,该进程在InputStream.read 调用中无限期阻塞。
  • netstat 显示与ServerSocket 的套接字连接仍然建立。即使发送数据的进程已终止,情况也是如此(在这种情况下,netstat -b 表明连接与进程 System 相关联。
  • 我已尝试在系统之间进行连接,但问题仍然存在。具体来说,我已经从 CentOS 虚拟机(由 Win 8.1 机器托管)连接到 Win 8.1 机器。在这种情况下,“发送”(CentOS)机器上的netstat 不会继续显示已建立的套接字,但“接收”(Windows 8.1)机器会显示已建立的套接字连接。
  • 我尝试通过环回接口 (127.0.0.1) 和实际网络接口(通过指定我的外部可见 IP)进行连接,结果相同。

自从升级到 Windows 8.1 后,我没有注意到任何其他网络问题。在 Windows 8 上运行时,相同的代码可以正常工作,因此操作系统升级似乎是关键。我的环境的细节:

  • Windows 8.1 Professional 64 位
  • Oracle HotSpot 7u40 JRE(尽管我尝试使用 7u45 和 6u37,得到相同的结果)
  • 戴尔灵越 5720
  • Realtek PCIe FE(有线)网络适配器正在使用中

Here is a Gist 的 Java 测试程序导致我的环境出现问题。 SocketListener 必须先运行。它将打印它已绑定到的套接字。使用 2 个参数运行 SocketTalker:运行 SocketListener 的主机和 SocketListener 绑定的端口。当问题发生时,SocketListener 会报告一个新的套接字连接,并且通常它至少已经收到了一些数据。但是,它不会报告套接字连接已关闭。

我认为SocketListener 可能包含错误,但它模拟了产品中使用的代码,该产品已在许多 Java 版本、JRE 实现和操作系统中成功运行多年。

任何在 Windows 中调试网络堆栈的技术都将不胜感激。我不是 Windows 开发人员...

编辑:

Here is a Wireshark capture 的问题样本。 192.168.1.26 是运行 SocketTalker 的 CentOS 机器,而 192.168.1.9 是运行 SocketListener 的 Win 8.1 机器。看起来 Windows 框在收到数据后停止响应。我可能在一切都说完之前就停止了捕获,但我想我得到了关键部分。

【问题讨论】:

  • 检查是否有用于 Realtek NIC 的更新驱动程序......只是一个想法......
  • 已升级到最新的 Realtek 驱动程序,但遗憾的是,这并没有什么不同。不过,谢谢你的想法。

标签: java sockets tcp windows-8.1


【解决方案1】:

您的服务器端永远不会关闭接受的套接字。这可能导致任何类型的不良行为,当然包括 ESTABLISHED 状态的持久性。

但是,您的 Wireshark 跟踪清楚地显示了传入的 FIN 和传出的 ACK,因此它似乎不是您描述的行为的实例。请注意,服务器没有传出 FIN,这证明了永远不会关闭接受的套接字的观点。

请注意,您的描述非常不准确。 ServerSocket 不参与 I/O。连接在客户端的Socket 和服务器上接受的Socket 之间。

【讨论】:

  • 关于忘记关闭套接字的公平点 - 我已将其添加到我的测试程序中,结果没有改变。请注意,该问题经常在 ServerSocket 接受的第一个连接上重现,因此它从来没有机会“不关闭”套接字,因为它是。 SocketListener 永远挂在 inputStream.read 中,永远不会收到“-1”返回值。
  • 关于 Wireshark 跟踪:第 6 帧似乎是对第 4 帧(PSH)的 ACK,而不是对第 5 帧中的 FIN 的 ACK。在第 7-11 帧中重复重试第 5 帧支持这一点.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多