Java NIO:IOException:Broken pipe 的意思是什么?

96
对于一些Java NIO连接,当我调用 SocketChannel.write(ByteBuffer)方法时,会抛出一个 IOException :“Broken pipe”。

什么会导致“broken pipe”,更重要的是,是否有可能从这种状态中恢复?如果无法恢复,似乎这将是一个好迹象,表明发生了不可逆转的问题,并且我应该简单地关闭此套接字连接。这是合理的假设吗?是否存在在套接字连接仍然正常连接而不是工作连接在某些情况下会引起此 IOException 的时间点?

顺便说一句,总是在尝试 SocketChannel.write()之前调用 SocketChannel.isConnected() 是否明智,如果是,我也可以假设如果 SocketChannel.isConnected() SocketChannel.isConnectionPending() 都为 false ,则该连接已“中断”,应将其关闭?

谢谢!

4个回答

109
什么会导致"broken pipe"错误,更重要的是,是否可能从这种状态中恢复?
它是由某些原因导致连接关闭。(不是您的应用程序关闭了连接:否则将导致不同的异常。)
不可能恢复连接。您需要打开一个新的连接。
如果无法恢复,那么似乎这表明发生了不可逆转的问题,我应该只需关闭此套接字连接。这是合理的假设吗?
是的,一旦收到该异常,套接字将永远无法再工作。关闭它是唯一明智的做法。
在socket连接仍然正确连接的情况下(而不是在某个时刻失败的工作连接),这种IOException会发生吗?
不会。(或者至少未经过OS网络堆栈、JVM和/或您的应用程序正确行为的破坏。)
是否明智始终在尝试SocketChannel.write()之前调用SocketChannel.isConnected()...?
通常,在使用(外部)资源r之前调用r.isXYZ()是不好的想法。在两个调用之间,资源的状态有很小的机会改变。更好的方法是执行操作,捕获由于失败的操作导致的IOException(或其他任何)并采取任何必要的补救措施。
在这种特殊情况下,调用isConnected()是无意义的。该方法被定义为在过去某个时间点连接了套接字时返回true。它不能告诉您连接是否仍然存活。确定连接是否仍然存活的唯一方法是尝试使用它;例如进行读取或写入。

23

断开管道(Broken pipe)简单地意味着连接已经失败。可以合理地假设这是无法恢复的,并且随后执行任何所需的清理操作(关闭连接等)。我认为你永远不会因为连接尚未完成而遇到这种情况。

如果您正在使用非阻塞模式,则SocketChannel.connect方法将返回false,您需要使用isConnectionPending和finishConnect方法来确保连接完成。通常我会基于事情会正常运行的预期进行编码,然后捕获异常以检测失败,而不是依赖频繁调用“isConnected”。


1
你不能在之前没有管道的情况下得到一个破损的管道。你不能在之前没有连接的情况下得到一个失败的连接。这个答案的最后一段是正确的,但不相关。 - user207421
这是一个问题还是计算机会处理好,麻烦告诉我。 - Kumaresan Perumal

22

断开的管道意味着你向另一端已经关闭的连接写入了数据。

isConnected() 无法检测到这种情况。只有写入操作才能检测到。

在尝试 SocketChannel.write() 操作之前,总是调用 SocketChannel.isConnected() 是否明智?

这是没有意义的。套接字本身已经连接。你已经连接它了。可能没有连接的是它内部的连接,而你只有通过尝试才能确定是否连接。


1

你应该假设另一端的套接字已关闭。在你的代码中加入一个try catch块来处理IOException异常。

你可以使用isConnected()方法来确定SocketChannel是否连接,但是在你的write()调用完成之前,它可能会发生变化。尝试在catch块中调用它,以查看是否这就是你收到IOException异常的原因。


5
在这种情况下,isConnected() 无论如何都会返回 true。可以理解为“套接字在过去某个时间点已连接”。 - kellogs
4
这个回答的最后一段完全是错误的。isConnected()方法不能检测到这种情况。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接