SocketChannel: java.io.IOException: существующее соединение было принудительно закрыто удаленным хостом - PullRequest
3 голосов
/ 12 апреля 2011

Я использую 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, даже если другой конец сокета был закрыт.

Что я могу / должен делать?

Ответы [ 2 ]

6 голосов
/ 12 апреля 2011

isOpen () и isConnected () должны быть более точно названы hasBeenOpenned () и hasBeenConnected (). Как только они верны, они не возвращаются к ложному.

Возможно, вам придется выполнить e.getMessage (). Contains («закрыто удаленным хостом»). К сожалению, это может зависеть от платформы.

Вместо этого я предлагаю вам разрешить протоколу отправлять какое-либо «закрытое» сообщение и рассматривать любое исключение без этого сначала как неожиданное.

2 голосов
/ 12 апреля 2011

Это может быть немного некрасиво ... Вы можете поиграть с этим. Дважды попробуйте код, поймав первое исключение и определив сообщение. Если это то, что вы ожидаете, игнорируйте это или делайте то, что вы собирались сделать раньше. Если это не то, что вы ожидали, бросьте это на более высокую попытку.

Теперь, когда я думаю об этом, вы можете сделать это за одну попытку, если хотите, просто взглянув на сообщение.

При этом, я думаю, вам следует пересмотреть идею полагаться на это исключение для контроля потока вашей программы. Вы уверены, что у вас должен быть дизайн, который говорит: «Я хочу, чтобы это исключение произошло»?

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
}
...