【问题标题】:Java socket read blocked/failed no exceptions thrown , setsotimer was set (TCP/IP)Java 套接字读取阻塞/失败没有抛出异常,设置了 setotimer (TCP/IP)
【发布时间】:2010-11-12 17:12:14
【问题描述】:

我们最近看到了这个错误。服务器向其中一个客户端发送了响应消息 (MSG1)(消息大小 > 64KB)。客户端读取时发生了一些事情,根本没有收到此消息。 SocketTimeOutException 和 IOException 都没有被抛出。服务器尝试发送另一条消息 (MSG2),但在写入时被阻止(TCP/IP 级别的缓冲区可能已被 MSG1 填满)。在我们意识到这一点并不得不重新启动一切之前已经过去了 2 个小时。我们设法通过让客户端读取速度变慢(暂停 2 秒)并使服务器像往常一样发送类似的消息(大小 >64KB)来模拟相同的事情。

首先,我们看不出客户端阅读速度慢的原因,几个月来它一直能够毫无问题地处理此类消息。我想知道(a)如果客户端读取了导致这种死锁的原因

getInputStream().read(byBuf)
比服务器写入慢
getOutputStream().write(MSG1)
byBuf 是一个大小为 512Bytes 的字节缓冲区) (b) 套接字错误或 n/w 错误是否会导致这种阻塞?

我们使用的是 jdk 1.6.0。

非常感谢!

【问题讨论】:

  • 如果您可以通过测试重现这一点,您应该启动 Wireshark 并查看网络跟踪以了解发生了什么。

标签: java sockets tcp


【解决方案1】:

如果套接字发送缓冲区已满,则写入阻塞,这意味着接收者的套接字接收缓冲区已满,这意味着读取器比写入器慢。由于您的阅读器在阅读中被阻止,这表明存在网络或内核问题。

【讨论】:

  • 感谢您的回复。当缓冲区已满且无法获得立即响应时,阻塞写入是否会无限期停止?
【解决方案2】:

听起来像是网络问题 - 可能是两台主机之间的链路拥塞或防火墙损坏。通过向客户端添加延迟来“重现”问题不会告诉您任何有趣的事情,只是操作系统级缓冲按设计工作:)

您需要找出数据包延迟的原因,这通常意味着两端都有tcpdump/wireshark。如果问题仅每隔几个月发生一次,那么这可能是矫枉过正 - 专注于改进应用程序处理这种情况的方式和/或如何检测它是否再次发生。

顺便说一句,Java 不允许设置写入超时,因此要从这种情况中恢复,reader 应该在读取之前调用setSoTimeout,然后在读取抛出时关闭套接字SocketTimeoutException。然后写入会失败并显示SocketException(“对等方重置连接”),但如果链接缓慢/间歇,这可能需要一段时间。

【讨论】:

  • 我们正在努力比以前更优雅地处理这种情况(如果它再次发生)。我们非常确定缓冲区已满,但无法理解为什么 read() 在没有抛出任何异常的情况下停止。我们假设我们首先看到的一切都是由于 n/w 问题。非常感谢您的回复1
猜你喜欢
  • 1970-01-01
  • 2012-11-18
  • 1970-01-01
  • 2021-03-03
  • 2012-08-16
  • 2019-02-06
  • 1970-01-01
  • 2012-12-18
  • 2011-12-27
相关资源
最近更新 更多