Как узнать, закрыл ли клиент соединение

Я играл с новыми асинхронными функциями Servlet 3.0 с Tomcat 7.0.4. Я нашел это приложение для чата, которое позволяет клиентам зависать на GET запрос на получение обновлений сообщения. Это работает просто отлично, когда дело доходит до получения сообщений.

Проблема возникает, когда клиент отключен, т.е. пользователь закрывает браузер. Похоже сервер не поднимает IOException, хотя клиент отключился. Поток сообщений (см. исходный код по ссылке выше) успешно пишет во все сохраненные выходные потоки AsyncContext.

Это ошибка Tomcat? или я что-то пропустил здесь? Если это не ошибка, то как я должен определить, закрыл ли клиент соединение?


person SS3    schedule 23.11.2010    source источник


Ответы (1)


Код в строке 44-47 позаботится об этом,

} catch(IOException ex) {
    System.out.println(ex);
    queue.remove(ac);
}

И здесь тоже на 75 - 83, используя таймаутную штучку,

req.addAsyncListener(new AsyncListener() {
    public void onComplete(AsyncEvent event) throws IOException {
        queue.remove(ac);
    }

    public void onTimeout(AsyncEvent event) throws IOException {
        queue.remove(ac);
    }
});

РЕДАКТИРОВАТЬ: после получения дополнительной информации.

  1. Tomcat 7.0.4 все еще находится в стадии бета-тестирования. Таким образом, вы можете ожидать такого поведения
  2. Я очень старался, но не могу найти ни метод setAsyncTimeout() в документе, ни здесь или здесь . Итак, я думаю, что они полностью удалили его в окончательной версии по какой-то неизвестной уважительной причине.
  3. В примере говорится: «почему я должен использовать инфраструктуру вместо ожидания Servlet 3.0 Async API». Из чего следует, что это написано до последней штуки

Итак, что я могу сказать, объединив все эти факты, что вы пытаетесь работать с тем, что в каком-то смысле сломано. Это также, возможно, причина различных и странных результатов.

person Adeel Ansari    schedule 23.11.2010
comment
Что ж, это позаботится об этом, если операция записи вызовет исключение IOException, которого не происходит. Таким образом, вы можете закрыть браузер и никогда не получить это исключение. И тайм-аут в этом примере 10 минут. Это довольно много, если у вас есть, скажем, сотни клиентов. - person SS3; 23.11.2010
comment
Я попробовал код с Glassfish v3, и кажется, что я могу получить событие onError с Firefox, но с IE это не сработает. Это действительно странно. - person SS3; 23.11.2010
comment
@SS3: Итак, можем ли мы сказать, что у вас нет проблем с Firefox? - person Adeel Ansari; 23.11.2010
comment
Вроде так, но мне нужно сделать еще несколько тестов. Я до сих пор не понимаю, почему это не работает с IE. А с Tomcat 7.0.4 это не работает даже с ФФ. - person SS3; 23.11.2010
comment
@SS3: Вы используете tab для доступа к приложению и закрытия вкладки? или вы закрываете окно IE и все его экземпляры? Это может показаться смешным, но раньше это имело значение. - person Adeel Ansari; 23.11.2010
comment
Я закрыл весь браузер, а не только вкладку. Это по-прежнему не объясняет, почему некоторые браузеры работают с Glassfish, но не с Tomcat. Должны быть проблемы с реализацией. - person SS3; 23.11.2010
comment
@ SS3: Просто браузер каким-то образом все еще где-то живет и потребляет сообщения, иначе вы должны были получить исключение. Но часть, где Tomcat не работает нормально, а GF работает, немного странная. Потому что GF фактически использует модифицированный Tomcat в качестве контейнера сервлетов. - person Adeel Ansari; 23.11.2010
comment
Действительно, от этого еще интереснее. - person SS3; 23.11.2010
comment
@SS3: Попробуйте сократить время ожидания. Кстати, я не вижу здесь этот метод, download.oracle .com/javaee/6/api/javax/servlet/ . Есть идеи. - person Adeel Ansari; 23.11.2010
comment
Тайм-аут является свойством AsyncContext, а не ServletResponse. Тайм-аут проблематичен, поскольку контейнер завершит асинхронный запрос, если он не завершится в течение заданного срока. Я не уверен, что запись в ответ AsyncContext сбросит этот таймер. - person SS3; 23.11.2010
comment
@ SS3: я имею в виду, попробуйте посмотреть строку 072 исходного примера первого фрагмента. Его вызов req.setAsyncTimeout(), которого нет в документах API. - person Adeel Ansari; 23.11.2010
comment
Ну да, кажется, он был перемещен в AsyncContext. Я не запускаю точно такой же код, но изменил его. Базовый функционал тот же. - person SS3; 23.11.2010
comment
@ SS3: Честно говоря, это здесь больше не актуально. Закройте этот вопрос, задайте новый с точным кодом, который вы реализовали. - person Adeel Ansari; 23.11.2010
comment
Хорошо, я отправлю новый вопрос с точным кодом. Но в конечном итоге я не думаю, что это будет иметь какое-либо значение. Спасибо за ваши ответы. - person SS3; 23.11.2010
comment
@ SS3: Возможно, мы сможем решить проблему, просмотрев ваш код. Мы потратили на это приличное количество времени, мы должны попытаться сделать хотя бы какой-то вывод. Что скажешь? - person Adeel Ansari; 23.11.2010