Java SocketChannel не обнаруживает отключение? - PullRequest
5 голосов
/ 15 августа 2010

У меня работает сокет с использованием селекторов.Я пытаюсь проверить, подключен ли мой сокет к серверу.

Boolean connected = _channel.isConnected();

, и он всегда возвращает true.Я отключил Аэропорт (подключение к интернету) на своем компьютере, и когда я проверяю, подключен ли сокет или нет, он все равно возвращает true.Есть идеи почему?Я пытаюсь записывать данные на сервер каждые 3 секунды, и это все еще не меняет состояние моего сокета на отключенное.

Ответы [ 3 ]

11 голосов
/ 15 августа 2010

Обычно, если вы отключаете работу на уровне ОС, при записи в сокет должны возникать исключения, поэтому вы знаете, что соединение разорвано.

Однако в целом мы не можем быть уверены, что пакет доставлен. В java (вероятно, тоже C) нет способа проверить, является ли пакет ACK.

Даже если мы сможем проверить TCP ACK, это не гарантирует, что сервер, получивший или , обработал пакет. Это только означает, что целевая машина получила пакет и буферизовала его в памяти. После этого многие вещи могут пойти не так.

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

С точки зрения клиента, он пишет сообщение на сервер, а затем пытается прочитать ACK с сервера. Если он его получает, он может быть уверен, что его сообщение получено и обработано. Если ему не удается получить ACK, он понятия не имеет, что произошло. Опытным путем, скорее всего, TCP не удалось. Следующая возможность - сбой сервера. Также возможно, что все прошло нормально, за исключением того, что ACK не смог связаться с клиентом.

5 голосов
/ 15 августа 2010

Канал сокета можно подключить, вызвав его метод подключения;После подключения канал сокета остается подключенным до тех пор, пока он не будет закрыт.

Канал не закрыт, когда сервер больше не доступен из-за разрыва физического соединения или сбоя сервера.Поэтому, как только соединение будет установлено, isConnected() будет возвращать true, пока вы не закроете канал на своей стороне.

Если вы хотите проверить, доступен ли сервер, отправьте байт нарозетки выходного потока.Если вы получили исключение, то сервер недоступен (соединение потеряно).


Редактировать

для EJP - некоторый код для проверки и пересмотра вашего комментария иответ:

public class ChannelTest {
     public static void main(String[] args) throws UnknownHostException, IOException {
      Socket google = new Socket(InetAddress.getByName("www.google.com"), 80);
      SocketChannel channel = SocketChannel.open(google.getRemoteSocketAddress());
      System.out.println(channel.isConnected());
      channel.close();
      System.out.println(channel.isConnected());
    }
}

Вывод на моей машине

true
false
4 голосов
/ 15 августа 2010

isConnected () сообщает, подключил ли вы объект channel , который у вас есть, и не указывается возвращать false после закрытия, хотя, очевидно, это так: смотрите Андреас ответ. Это не значит, что базовое соединение все еще существует. Вы можете только сказать, что, используя его: -1 из чтения или исключения говорит вам, что.

...