对于我的一些Java NIO连接,当我进行SocketChannel.write(ByteBuffer)
调用时,它会抛出IOException
:“断管”。
导致“管道破裂”的原因是什么,更重要的是,是否可以从该状态恢复?如果它无法恢复,似乎这是一个好的迹象,表明发生了不可逆转的问题,我应该简单地关闭这个套接字连接。这是一个合理的假设吗?在套接字连接仍然是首先正确连接时(而不是某个时候失败的工作连接),是否有时间会出现IOException
?
另一方面,在尝试SocketChannel.isConnected()
之前总是调用SocketChannel.write()
是明智的,如果是这样,我是否也可以假设连接已“断开”并且如果两者都应该关闭{ {1}}和SocketChannel.isConnected()
都是SocketChannel.isConnectionPending()
?
谢谢!
答案 0 :(得分:94)
是什么导致“破管”,更重要的是,是否可以从该状态恢复?
它是由导致连接关闭的东西引起的。 (关闭连接不是你的应用程序:这会导致一个不同的异常。)
无法恢复连接。你需要开一个新的。
如果无法恢复,似乎这是一个很好的迹象,表明发生了不可逆转的问题,我应该简单地关闭这个套接字连接。这是一个合理的假设吗?
是。一旦收到该异常,套接字将无法再次运行。关闭它是唯一明智的做法。
在套接字连接首次正确连接时(而不是某个时刻失败的工作连接),是否有时间会出现
IOException
?
没有。 (或者至少,并非没有颠覆OS网络堆栈,JVM和/或您的应用程序的正确行为。)
在尝试
SocketChannel.isConnected()
之前始终致电SocketChannel.write()
是否明智...
通常,在使用(外部)资源r.isXYZ()
的某个调用之前调用r
是个坏主意。 两次调用之间的资源状态很可能会发生变化。最好的做法是执行操作,捕获失败操作产生的IOException
(或其他),并采取任何必要的补救措施。
在这种特殊情况下,调用isConnected()
毫无意义。如果套接字在过去的某个时刻连接,则该方法被定义为返回true
。它不会告诉您连接是否仍然有效。确定连接是否仍然存在的唯一方法是尝试使用它;例如做一个读或写。
答案 1 :(得分:22)
断管只是意味着连接失败。可以合理地假设这是不可恢复的,然后执行任何所需的清理操作(关闭连接等)。我不相信你会因为连接尚未完成而看到这一点。
如果使用非阻塞模式,则SocketChannel.connect方法将返回false,您将需要使用isConnectionPending和finishConnect方法来确保连接完成。我通常会根据事情的预期进行编码,然后捕获异常来检测故障,而不是依赖频繁调用“isConnected”。
答案 2 :(得分:17)
管道损坏意味着您已写入已被另一端关闭的连接。
isConnected()
未检测到此情况。只写一次。
在尝试SocketChannel.write()
之前总是调用SocketChannel.isConnected()是明智的吗?
毫无意义。 套接字本身已连接。你连接了它。 可能未连接的是连接本身,您只能通过尝试来确定它。
答案 3 :(得分:1)
您应该假设套接字已在另一端关闭。使用try catch块包装代码以获取IOException。
您可以使用isConnected()来确定SocketChannel是否已连接,但在write()调用完成之前可能会更改。尝试在catch块中调用它,看看实际上这是否是你获得IOException的原因。