сокет закрывается после отказа соединения - это нормальное поведение? - PullRequest
0 голосов
/ 05 марта 2020

Я играю с android интерфейсом сокета, я понял из документации, что методы .isConnected () и isClosed () ничего не говорят о состоянии сокета, но, тем не менее, это указание, если мы вызывали connect и close на сокет.

В моем приложении я выполняю повтор с задержкой в ​​10 секунд между попытками, я вижу странную вещь, если я получаю отказ в соединении от сервера, мои следующие попытки терпят неудачу, потому что сокет закрыт.

так ли это на самом деле?

вот моя функция подключения:

  private boolean ConnectToServer() {
        int retry = 0;
        try {
            ServerIP = InetAddress.getByName(mServer);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        SocketAddress mSocketAddress = new InetSocketAddress(ServerIP, mPort);

        while ((!mSocket.isConnected()) && retry < 10) {
            mLogger.setMessage("Status isConnected:"+mSocket.isConnected()+"Status isClosed:"+mSocket.isClosed());
            mLogger.sendLog();
            try {
                mSocket.connect(mSocketAddress, 3000);
            } catch (IOException e) {
                e.printStackTrace();
            }
            retry++;
            mLogger.setMessage("Attempting to connect to server - Sleeping for 5 Seconds Rety="+retry);
            mLogger.sendLog();
            SystemClock.sleep(5000);
        }
        mLogger.setMessage("Returning from attempting connection with socket status "+mSocket.isConnected());
        return mSocket.isConnected();

    }

и вот соответствующие журналы

2020-03-05 09:51:37.200 23239-23296/com.eddieharari.poker5o D/poker5o: Buildup new Socket - still null isclosed=false
    2020-03-05 09:51:37.201 23239-23296/com.eddieharari.poker5o D/poker5o: Status isConnected:falseStatus isClosed:false
    2020-03-05 09:51:37.203 23239-23296/com.eddieharari.poker5o W/System.err: java.net.ConnectException: failed to connect to /10.0.2.2 (port 55555) from /10.0.2.15 (port 39702) after 3000ms: isConnected failed: ECONNREFUSED (Connection refused)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at libcore.io.IoBridge.isConnected(IoBridge.java:288)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at libcore.io.IoBridge.connectErrno(IoBridge.java:193)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:135)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.Socket.connect(Socket.java:621)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at com.eddieharari.poker5o.SignalChannel.ConnectToServer(SignalChannel.java:95)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at com.eddieharari.poker5o.SignalChannel.manageConnection(SignalChannel.java:109)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at com.eddieharari.poker5o.SignalChannel.run(SignalChannel.java:57)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err: Caused by: android.system.ErrnoException: isConnected failed: ECONNREFUSED (Connection refused)
    2020-03-05 09:51:37.206 23239-23296/com.eddieharari.poker5o W/System.err:     at libcore.io.IoBridge.isConnected(IoBridge.java:275)
    2020-03-05 09:51:37.207 23239-23296/com.eddieharari.poker5o W/System.err:   ... 11 more
    2020-03-05 09:51:37.207 23239-23296/com.eddieharari.poker5o D/poker5o: Attempting to connect to server - Sleeping for 5 Seconds Rety=1
    2020-03-05 09:51:42.208 23239-23296/com.eddieharari.poker5o D/poker5o: Status isConnected:falseStatus isClosed:false
    2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err: java.net.SocketException: Socket closed
    2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:139)
    2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
    2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.Socket.connect(Socket.java:621)
2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at com.eddieharari.poker5o.SignalChannel.ConnectToServer(SignalChannel.java:95)
2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at com.eddieharari.poker5o.SignalChannel.manageConnection(SignalChannel.java:109)
2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o W/System.err:     at com.eddieharari.poker5o.SignalChannel.run(SignalChannel.java:57)
2020-03-05 09:51:42.209 23239-23296/com.eddieharari.poker5o D/poker5o: Attempting to connect to server - Sleeping for 5 Seconds Rety=2
2020-03-05 09:51:44.291 23239-23273/com.eddieharari.poker5o D/EGL_emulation: eglMakeCurrent: 0xdb61a120: ver 3 0 (tinfo 0xdb60f1d0)
2020-03-05 09:51:47.211 23239-23296/com.eddieharari.poker5o D/poker5o: Status isConnected:falseStatus isClosed:false
2020-03-05 09:51:47.212 23239-23296/com.eddieharari.poker5o W/System.err: java.net.SocketException: Socket closed
2020-03-05 09:51:47.212 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:139)
2020-03-05 09:51:47.212 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
2020-03-05 09:51:47.212 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
2020-03-05 09:51:47.212 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
2020-03-05 09:51:47.212 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
2020-03-05 09:51:47.213 23239-23296/com.eddieharari.poker5o W/System.err:     at java.net.Socket.connect(Socket.java:621)

Как вы можете см. из журнала, когда я вызываю до подключения к методу isClosed, он возвращает false, но сразу после того, как я пытаюсь подключиться, и полученное исключение - закрытый сокет.

Единственный раз, когда я не получаю закрытый сокет, это с первой попытки это заставляет меня понять, что ОС закрывает сокет ... однако, как я могу попытаться выполнить rety в таком случае, а также как узнать, закрыла ли сокет ОС по какой-то другой причине?

1 Ответ

1 голос
/ 05 марта 2020

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

Это действительно так?

Да. Неудачное соединение закроет Socket, и вы не сможете использовать его снова.

Это заставляет меня понять, что ОС закрывает сокет.

На самом деле, в некоторых случаях закрытие инициируется Java. (Не то, чтобы это действительно имело значение.)

Как я могу попытаться повторить попытку в таком случае.

Вам нужно отбросить объект Socket, создать еще один и подключиться с , что . Basi c retry logi c выглядит примерно так:

SocketAddress address = new InetSocketAddress(...);
while (retry <= NOS_RETRIES) {
    Socket = new Socket();
    try {
        socket.connect(address, port);
        return socket;
    } catch (IOException e) {
        // possibly log exception
        if (/* it makes no sense to retry */) {
           // rethrow e, or return null
        }
    retry++;
    // delay
}
// rethrow last e, or return null

Как узнать, закрыла ли сокет ОС по какой-то другой причине?

Вы можете перехватить и изучить возникшее исключение, чтобы определить причину сбоя вызова connect.

Точные исключения, которые будут выброшены, зависят от контекста и не указано. Списки javadoc IOException, IllegalBlockingModeException или IllegalArgumentException, но в действительности возможны также различные типы IOException. К ним относятся:

  • UnknownHostException - если вы используете InetAddress с именем хоста, а имя хоста неизвестно.
  • BindException - обычно локальный порт уже подключен используйте
  • ConnectException - соединение отклонено или истекло время ожидания попытки соединения,
  • SocketTimeoutException - истекло время попытки соединения,
  • NoRouteToHostException - обычно удаленный хост отключен ,
  • ProtocolException - ошибка протокола транспортного уровня,
  • SocketException - для различных вещей, таких как попытка подключения подключенного или закрытого сокета.

Некоторые из них не будут применяться к вашему варианту использования, а другие могут никогда не встретиться на практике.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...