SocketChannel: java.io.IOException: 远程主机强制关闭了一个现有的连接。

3

我正在使用一个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,即使套接字的另一端已关闭。
我该怎么做?

等等,这是预期的吗?也就是说,你真的希望它发生? - corsiKa
我不希望它发生,但它经常发生:当套接字的另一端想关闭它时,它就会关闭。 我没有内部机制来说“好的,再见!” 让服务器知道何时停止通信,所以我只能处理。 而且网络可能会崩溃,或出现其他问题。 我想将这种情况视为正常情况。 - Jason S
2个回答

6

isOpen()和isConnected()应该更准确地被称为hasBeenOpenned()和hasBeenConnected()。一旦它们为真,它们不会返回为假。

你可能需要执行e.getMessage().contains("closed by the remote host")。不幸的是,这很可能是平台相关的。

相反,我建议允许协议发送某种“已关闭”的消息,并将没有此消息的任何异常视为意外情况。


2
这可能有点丑陋……你可以用它来玩接力。双重尝试代码,捕获第一个异常并确定消息。如果是你所期望的,请忽略它,或者执行你原本要做的操作。如果不是你所期望的,请将其抛到更高层的 try 中。
现在我想起来了,如果你想的话,你可以在一个 try 中完成这个操作,只需查看消息即可。
话虽如此,我认为你应该重新评估依赖此异常控制程序流程的想法。你确定你应该有一个这样的设计,即“我希望发生这个异常吗?”?
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
}

是的,我必须承认 - 我不喜欢这段代码。我试图遵循“如果发生异常,就意味着有 bug”的心态。虽然我理解你的情况。有时候我们确实没有时间/资金/政策来按照自己的想法去做事。 :-( - corsiKa
2
我不知道为什么Sun没有抛出ClosedChannelException。 - Jason S
如果我必须这样做,我会使用你的方法,否则彼得有一点是正确的,即发送某种关闭消息更可取;我会找到办法。唉。 - Jason S
@Jason S:因为ClosedChannelException表示已关闭通道。在OP的情况下,通道没有关闭,连接已关闭。 - user207421
2
@EJP:(OP = 我)-- 那么他们应该定义一个ConnectionClosedException或其他异常。 - Jason S
显示剩余4条评论

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