我正在使用带有网络套接字的SocketChannel,并且必须处理意外关闭通道的套接字另一端的预期异常。
问题是,我得到了这个IOException:
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(Unknown Source)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
at sun.nio.ch.IOUtil.read(Unknown Source)
at sun.nio.ch.SocketChannelImpl.read(Unknown Source)
...
我需要区分这个预期会发生的异常和意外的异常,以便我可以记录/打印意外的异常并处理这个异常。但它只是一个普通的IOException,带有不同的文本消息,虽然我总是检查SocketChannel.isOpen()和SocketChannel.isConnected(),但在这种情况下它们似乎返回true,即使套接字的另一端已经关闭。 / p>
我能做什么/应该做什么?
答案 0 :(得分:6)
isOpen()和isConnected()应该更准确地称为hasBeenOpenned()和hasBeenConnected()。一旦它们成立,它们就不会回归虚假。
您可能必须执行e.getMessage()。contains(“由远程主机关闭”)。不幸的是,这很可能取决于平台。
相反,我建议您允许协议发送某种类型的“已关闭”消息,并将此处的任何异常视为意外。
答案 1 :(得分:2)
这可能有点难看......你可以玩它。双击代码,捕获第一个异常并确定消息。如果这是你的期望,忽略它,或做你以前要做的事情。如果它不是你所期望的那样,那就把它扔到更高的尝试。
现在我想到了,如果你愿意的话,你可以在一次尝试中做到这一点,只需查看信息。
话虽如此,我认为您应该重新评估依赖此异常来控制程序流程的想法。你确定你应该有一个设计说“我想要发生这个例外”吗?
try {
try {
// your code
} catch(IOException innerIOE) {
if(innerIOE.getMessage().begins("An existing connection was forcibly closed")) {
log.info("Exception expected, yay.");
}
else {
throw innerIOE;
}
} // end inner catch
} catch(IOException outerIOE) {
// error handling code here, your "An existing connection was forcibly closed"
// shouldn't make it out here
}