Действительно ли возможно закрыть сокеты Java на обеих сторонах клиента и сервера?

У меня есть соединение TCP сокета между двумя JAVA-приложениями. Когда одна сторона закрывает сокет, другая сторона остается открытой. но я хочу, чтобы это было закрыто. И также я не могу дождаться, чтобы на нем видеть, доступно ли это или не и после того завершения это. Я хочу некоторый способ закрыть его полностью с одной стороны. Что я могу сделать?

7
задан tshepang 4 February 2014 в 15:30
поделиться

5 ответов

TCP так не работает. ОС не будет освобождать ресурсы, а именно дескриптор файла и, следовательно, порт, пока приложение явно не закроет сокет или не умрет, даже если стек TCP знает, что другая сторона закрыла его. Нет обратного вызова от ядра к пользовательскому приложению при получении FIN от однорангового узла. ОС подтверждает это другой стороне, но ожидает, пока приложение вызовет close () , прежде чем отправить свой пакет FIN. Взгляните на диаграмму перехода состояний TCP - вы находитесь в поле пассивное закрытие .

Один из способов обнаружить подобную ситуацию без выделения потока каждому сокету - использовать семейство функций select / poll / epoll / kqueue . Пассивно закрытый сокет будет обозначен как доступный для чтения, а попытка чтения вернет EOF.

Надеюсь, это поможет.

10
ответ дан 6 December 2019 в 08:14
поделиться

Обычное решение - позволить другой стороне знать, что вы собираетесь закрыть соединение, прежде чем на самом деле закрыть его. Например, в случае протокола SMTP-протокола сервер отправит «221 BYE», прежде чем он закрывает соединение.

3
ответ дан 6 December 2019 в 08:14
поделиться

Если вы все еще читаете со своего сокета, вы обнаружите -1, когда он закрывается.

Если вы больше не читаете от розетки, продолжайте и закройте его.

Если это ни один из них, у вас, вероятно, наличие потока ждут события. Это не так, как вы хотите обращаться с тысячами портов! Java начнет получать Pukey примерно на 3000 потоков в Windows - намного меньше в Linux (я не знаю почему).

Убедитесь, что вы используете NIO. Используйте один поток для управления всеми вашими портами (пул подключения). Он должен просто взять данные из потока, переслать его в очередь. В этот момент я думаю, что у меня будет пул нить, возьмите данные из очередей и обрабатывают его, потому что фактически обработка данных из порта займет некоторое время.

Присоединение нити к каждому порту не будет работать, и была самая большая причина, по которой нужна NIO.

Также, имея какое-то «закрытие» сообщение как часть вашего потока, чтобы вызвать закрытие порта, может заставить вещи работать быстрее - но вам все равно нужно обрабатывать -1, чтобы покрыть случай сломанных потоков

4
ответ дан 6 December 2019 в 08:14
поделиться

Вы, вероятно, хотите иметь соединительный пул.

-1
ответ дан 6 December 2019 в 08:14
поделиться

Обе стороны должны читать из соединения, чтобы они могли определить, когда одноранговый узел закрылся. Когда read возвращает -1, это будет означать, что другой конец закрыл соединение, и это ваш ключ к закрытию вашего конца.

6
ответ дан 6 December 2019 в 08:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: