Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > Socket.close()


Автор: Konigsberg 11.12.2005, 05:10
Если при выполнении Socket.close() произошло исключение IOException, считать что соединение завершено или незавершено?

Автор: batigoal 11.12.2005, 14:22
Боюсь, что поведение в этом случае будет неопределенным.

Автор: Konigsberg 11.12.2005, 16:21
А чисто теоретически когда может возникнуть это исключение?

Автор: LSD 11.12.2005, 21:37
Вот в этом участке кода происходит реальное закрытие сокета:
Код
    protected void close() throws IOException {
    synchronized(fdLock) {
        if (fd != null || fd1 != null) {
        if (fdUseCount == 0) {
            if (closePending) {
            return;
            }
            closePending = true;
            /*
             * We close the FileDescriptor in two-steps - first the
             * "pre-close" which closes the socket but doesn't
             * release the underlying file descriptor. This operation
             * may be lengthy due to untransmitted data and a long
             * linger interval. Once the pre-close is done we do the
             * actual socket to release the fd.
             */
            try {
                socketPreClose();
            } finally {
                socketClose();
            }
            fd = null;
            fd1 = null;
            return;
        } else {
            /*
             * If a thread has acquired the fd and a close
             * isn't pending then use a deferred close.
             * Also decrement fdUseCount to signal the last
             * thread that releases the fd to close it.
             */
            if (!closePending) {
            closePending = true;
                fdUseCount--;
            socketPreClose();
            }
        }
        }
    }
    }

Методы socketPreClose() и socketClose() в итоге обращаются к нативному методу private native void socketClose0(boolean), вот он и может выкинуть ошибку (больше там вроде ничего ее не выкидывает). Как я понимаю там идет обращение к ОС, и одназначно сказать какая ОС какую ошибку выкинет нельзя. Скорее это будет проблема с дескрипторами и т.п. чем проблема с сетью, в результате экспериментов заставить Sockect.close() выкинуть ошибку мне не удалось.

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

Автор: Konigsberg 11.12.2005, 21:53
LSD, пасиб, буду считать соединение разорванным.

Автор: COVD 12.12.2005, 17:06
Когда вы закрываете сокет на одном конце (например, на сервере ), то другой сокет (например, клиентский) об этом все равно ничего не знает. Закрылся сокет или нет на сервере, клиентский сокет может узнать только при попытке что-то послать на сервер. Если же клиентский сокет только "слушает", то он будет слушать вечно.

Когда вы закрываете соединение (сокет) на одном конце, это не значит, что сокет перед закрытием доложит сокету на другом конце о своей кончине. Он просто тихо помрет или выбросит исключение, но это не связано с состоянием сети. Сокет при закрытии ничего никому не пересылает. Такое мое представление.

Автор: val 12.12.2005, 17:56
Цитата
Такое мое представление.


Да, верно, я это проверял на практике.

Автор: LSD 12.12.2005, 22:31
Цитата(COVD @ 12.12.2005, 17:06)
Когда вы закрываете соединение (сокет) на одном конце, это не значит, что сокет перед закрытием доложит сокету на другом конце о своей кончине. Он просто тихо помрет или выбросит исключение, но это не связано с состоянием сети. Сокет при закрытии ничего никому не пересылает. Такое мое представление.

У тебя не правильное представление. Почитай главу 3.5. Closing a Connection в ftp://ftp.rfc-editor.org/in-notes/rfc793.txt (http://www.citforum.ru/internet/tifamily/tcpspec.shtml).

Попробуй на клиенте открыть поток и читать из него данные, а на сервере закрыть его. Ты сразу получишь на клиенте end of stream.

Автор: COVD 12.12.2005, 23:35
Если закрыть сокет на сервере во время передачи данных, то клиент об этом узнает, потому что согласно протоколу TCP/IP клиентский сокет подтверждает серверу получение данных, т.е. шлет на сервер подтверждение. Но если порция данных успешно прочитана, и клиентский сокет ждет новую порцию, то может и не дождаться, если серверный сокет помер.

За ссылку спасибо. Там сказано, что сокеты при закрытие друг другу должны посылать FIN. Однако у меня сложилось ощущение, что это не всегда срабатывает. Возможно, зависит от того как сокет помер (компьютер завис вот и не успел сокет доложить по форме?).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)