У меня есть соединение TCP сокета между двумя JAVA-приложениями. Когда одна сторона закрывает сокет, другая сторона остается открытой. но я хочу, чтобы это было закрыто. И также я не могу дождаться, чтобы на нем видеть, доступно ли это или не и после того завершения это. Я хочу некоторый способ закрыть его полностью с одной стороны. Что я могу сделать?
TCP так не работает. ОС не будет освобождать ресурсы, а именно дескриптор файла и, следовательно, порт, пока приложение явно не закроет сокет или не умрет, даже если стек TCP знает, что другая сторона закрыла его. Нет обратного вызова от ядра к пользовательскому приложению при получении FIN от однорангового узла. ОС подтверждает это другой стороне, но ожидает, пока приложение вызовет close ()
, прежде чем отправить свой пакет FIN. Взгляните на диаграмму перехода состояний TCP - вы находитесь в поле пассивное закрытие .
Один из способов обнаружить подобную ситуацию без выделения потока каждому сокету - использовать семейство функций select / poll / epoll / kqueue
. Пассивно закрытый сокет будет обозначен как доступный для чтения, а попытка чтения вернет EOF.
Надеюсь, это поможет.
Обычное решение - позволить другой стороне знать, что вы собираетесь закрыть соединение, прежде чем на самом деле закрыть его. Например, в случае протокола SMTP-протокола сервер отправит «221 BYE», прежде чем он закрывает соединение.
Если вы все еще читаете со своего сокета, вы обнаружите -1, когда он закрывается.
Если вы больше не читаете от розетки, продолжайте и закройте его.
Если это ни один из них, у вас, вероятно, наличие потока ждут события. Это не так, как вы хотите обращаться с тысячами портов! Java начнет получать Pukey примерно на 3000 потоков в Windows - намного меньше в Linux (я не знаю почему).
Убедитесь, что вы используете NIO. Используйте один поток для управления всеми вашими портами (пул подключения). Он должен просто взять данные из потока, переслать его в очередь. В этот момент я думаю, что у меня будет пул нить, возьмите данные из очередей и обрабатывают его, потому что фактически обработка данных из порта займет некоторое время.
Присоединение нити к каждому порту не будет работать, и была самая большая причина, по которой нужна NIO.
Также, имея какое-то «закрытие» сообщение как часть вашего потока, чтобы вызвать закрытие порта, может заставить вещи работать быстрее - но вам все равно нужно обрабатывать -1, чтобы покрыть случай сломанных потоков
Обе стороны должны читать из соединения, чтобы они могли определить, когда одноранговый узел закрылся. Когда read возвращает -1, это будет означать, что другой конец закрыл соединение, и это ваш ключ к закрытию вашего конца.