#java #nio
#java #nio
Вопрос:
У меня есть вопрос со ссылкой на это руководство
http://rox-xmlrpc.sourceforge.net/niotut/
В методе read сервера, если read возвращает -1, всегда ли это означает, что клиент закрыл соединение??
Я перевел примерный клиент в режим ожидания на длительное время после отправки сообщения, я вижу, что selector.select () не блокируется и продолжает выбирать канал как доступный для чтения, даже если клиент ничего не отправляет, а метод server reads считывает и возвращает -1, и таким образом закрывает канал, но клиент не отключился.
Я не понимаю такого поведения. Может ли кто-нибудь помочь мне понять?
Я пытаюсь модифицировать сервер так, чтобы сервер не отключался от клиента, даже если клиент ничего не отправляет, и поэтому он должен блокировать selector.select() .
Спасибо!
Ответ №1:
API должен работать, как описано. Чтение вернет -1, когда соединение с сокетом будет закрыто. Это не то же самое, что «конец сообщения». Соединение может быть закрыто по истечении времени ожидания, и я отмечаю, что вы сказали, что клиент ждал «долгое время».
Я также отмечаю, что вы работаете с конкретным руководством. Клиентский код в этом руководстве специально закрывает соединение после получения ответа и открывает новое для каждой отправки. Вам пришлось бы внести большие изменения в дизайн кода клиента, чтобы остановить это.
Когда я запускаю сервер nio из этого руководства с клиентом, который не закрывает соединение, поведение соответствует описанию API — серверный поток ожидает в Selector.select(), пока клиент спит между отправкой сообщений.
Следовательно, мой ответ заключается в том, что вы, вероятно, используете клиент, который закрывает соединения, и если нет, то «долгое время», которого вы ждете, может привести к тому, что сеть закроет соединения для вас. Учитывая поведение, которое вы описываете, я почти уверен, что это первое.
Ответ №2:
В методе чтения сервера, если чтение возвращает -1, всегда ли это означает, что клиент закрыл соединение?
ДА. Всегда.
сервер считывает, метод считывает и возвращает -1 и, таким образом, закрывает канал, но клиент не отключился.
Да, это так. Вот что это значит. Клиент закрыл соединение.
Комментарии:
1. Мне это нравится. Два необъяснимых отрицательных отзыва, и это также помечено как правильное, что так и есть.
Ответ №3:
Я предполагаю — но я не совсем уверен, потому что я не прочитал это полностью — вы не понимаете различия между подключением к порту и подключением к сокету. Насколько я понимаю, соединение открывается через сокет на определенном порту. Сокет мог быть закрыт соответственно. получено окончание сообщения, которое было отправлено, но соединение все еще могло сохраниться.
Насколько я понимаю, -1 указывает на окончание сообщений, отправленных через сокет-соединение. Нет четкого индикатора, который напрямую сообщает вам, что соединение закрыто…. Вы должны придумать это самостоятельно. (Мои 2 цента понимания.)
Комментарии:
1. Этот ответ имеет очень мало смысла. Не существует такого понятия, как подключение к порту, в отличие от подключения к сокету. Есть только соединения. Если одноранговый узел закрыл соединение, вы получаете -1. Если вы закрыли его самостоятельно, вы получите исключение SocketClosedException. Третьей возможности нет. Вы не можете закрыть порт или соединение, вы можете закрыть только сокет, который является вашей конечной точкой для соединения.
2. Вы можете установить соединение, например, на порту 3500. Сервер мог установить 3 соединения с сокетами на порт 3500. Если одно из 3 сокет-соединений закрыто, вы получаете для одного закрытого значение -1, но два других соединения остаются открытыми (на порту 3500).
3. [РЕДАКТИРОВАТЬ было невозможно, поэтому остальное] То, что вы, EJP, пишете, допустимо только в том случае, если у вас есть соединение с ОДНИМ сокетом на порт, а не несколько соединений с сокетами через один порт. Таким образом, получение -1 не обязательно означает, что «клиент отключен от сервера», но будет означать «ОДНО сокет-соединение от ОДНОГО клиента закрыто». т. Е. -1 все еще может означать, что другое соединение остается активным.
4. @LeO: Ваша терминология настолько неточна, что трудно сказать, о чем именно вы говорите. (1) Не существует такого понятия, как «соединение с сокетом» или «через один порт». Существуют (i) порты, (ii) соединения и (iii) сокеты. (2) Если одноранговый узел закрывает соединение, вы считываете -1 на нем. Если вы прочитали -1 в соединении, одноранговый узел закрыл его. (3) В ситуации, которую вы сейчас описываете, фраза «клиент отключился от сервера» не имеет смысла. Я этим не пользовался. Вы сделали. В этой ситуации соединение, по которому вы прочитали -1, было закрыто, остальные остаются открытыми.
5. @Leo Ты сказал, что сокет может быть закрыт соответственно. получено окончание сообщения, которое было отправлено, но соединение все еще могло сохраниться.’ Это просто неверно. Это соединение закрыто. Точка. Другие соединения могут существовать, а могут и не существовать, и их чтение может возвращать -1, а может и не возвращать. Это безвозвратно. И концепция «клиент, отключающийся от сервера» по ряду подключений, по-прежнему не имеет никакого реального значения. И мой отрицательный отзыв касается точности вашего ответа, а не вашего намерения. Вот как это работает.