SocketChannel:java.io.IOException:远程主机强制关闭现有连接

时间:2011-04-12 16:00:44

标签: java sockets exception-handling nio

我正在使用带有网络套接字的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>

我能做什么/应该做什么?

2 个答案:

答案 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
}