автоматическое закрытие веб-сокета - PullRequest
66 голосов
/ 29 января 2012

Я создаю приложение на Java, которое имеет встроенный сервер веб-сокетов на базе Jetty. Клиент является реализацией веб-сокета по умолчанию в Google Chrome. Все работает нормально, только если не происходит передачи между сервером и клиентом через определенное время, соединение закрывается. Я не уверен, кто закрывает соединение: сервер Jetty или браузер Chrome.

Я думаю, что решение этой проблемы - отправлять сообщения каждые x секунд, но я открыт для более эффективных решений.

ТАК ... мои вопросы:

  1. Требуется ли это протокол веб-сокета, и в этом случае браузер Chrome закрывает мое соединение?

  2. Является ли это чем-то более связанным с причалом и более или менее связанным с протоколом websocket? В этом случае, как отключить это в пристани?

  3. Есть ли другая проблема ??

Спасибо

ОБНОВЛЕНИЕ: даже если я отправляю 1 сообщение / секунду, соединение закрыто

Ответы [ 9 ]

37 голосов
/ 09 марта 2015

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

Решение состоит в том, чтобы прослушивать onclose события на клиенте веб-сокета и, когда они происходят, установить тайм-аут на стороне клиента для повторного открытия соединения, скажем, в секунду:

function setupWebSocket(){
    this.ws = new WebSocket('wss://host:port/path');
    this.ws.onerror = ...;
    this.ws.onopen = ...;
    this.ws.onmessage = ...;
    this.ws.onclose = function(){
        setTimeout(setupWebSocket, 1000);
    };
}
15 голосов
/ 26 октября 2012

Вам необходимо время от времени отправлять сообщения ping. Я думаю, что время ожидания по умолчанию составляет 300 секунд. Отправка ping / pong-кадра веб-сокета из браузера

9 голосов
/ 15 августа 2012

Я нашел другое, довольно быстрое и грязное решение.Если вы используете низкоуровневый подход для реализации WebSocket и сами реализуете метод onOpen, вы получаете объект, реализующий интерфейс WebSocket.Connection.Этот объект имеет метод setMaxIdleTime , который вы можете настроить.

6 голосов
/ 04 апреля 2014

Вы можете фактически установить интервал ожидания в конфигурации на стороне сервера Jetty, используя экземпляр WebSocketServletFactory.Например:

        WebSocketHandler wsHandler = new WebSocketHandler()
        {
            @Override
            public void configure(WebSocketServletFactory factory)
            {
                factory.getPolicy().setIdleTimeout(1500);
                factory.register(MyWebSocketAdapter.class);
                ...
            }
        }
4 голосов
/ 27 июня 2012

Только что нашел решение для себя. То, что вы хотите установить, это maxIdleTime WebSocketServlet, в миллис. Как это сделать, зависит от того, как вы настроили свой сервлет. С Guice ServletModule вы можете сделать что-то подобное за время ожидания 10 часов:

serve("ws").with(MyWSServlet.class, 
new HashMap<String, Sring>(){{ put("maxIdleTime", TimeUnit.HOURS.toMillis(10) + ""); }});

Я верю, что все, что <0, бесконечно просто. </p>

3 голосов
/ 30 января 2012

Я полагаю, что это проблема причала.Я не видел, чтобы браузеры закрывали соединения WebSocket из-за неактивности, и я не сталкивался с другими серверами WebSocket, которые превышают время ожидания соединений WebSocket.

Jetty (в основном) была (была) ориентирована на создание сервлетов приложений на основе HTTP.В этом контексте HTTP-соединения необходимо очищать довольно агрессивно, а HTTP не был предназначен для долговременных соединений, поэтому разумно иметь короткий тайм-аут по умолчанию.

Я не видел точную проблему, которую вы описали (закрытие даже во время активности), но я вижу, что соединения WebSocket закрываются после 30 секунд бездействия.Вполне возможно, что в более старых версиях Jetty или в текущей версии по какой-либо другой причине таймер не сбрасывается активностью WebSocket.Я обхожу это, используя метод setMaxIdleTime в моем объекте BlockingChannelConnector, чтобы установить значение тайм-аута в Integer MAX_VALUE.

2 голосов
/ 30 июня 2014

Вот пример того, как настроить время ожидания веб-сокета Jetty (наиболее вероятный виновник) с помощью WebSocketServlet (в scala, извините, но синтаксис почти такой же).

import javax.servlet.annotation.WebServlet
import org.eclipse.jetty.websocket.servlet.{WebSocketServletFactory, WebSocketServlet}

@WebServlet(name = "WebSocket Servlet")
class WebsocketServlet extends WebSocketServlet {
  override def configure(factory: WebSocketServletFactory): Unit = {
    factory.getPolicy.setIdleTimeout(1000 * 3600)
    factory.register(classOf[ClientWebsocket])
  }
}
2 голосов
/ 30 января 2012

Я думаю, что этот тайм-аут на самом деле является частью TCP / IP, и решение состоит в том, чтобы просто время от времени отправлять пустые сообщения.

1 голос
/ 10 февраля 2015

У меня похожий опыт, и я считаю, что это может быть браузер, который сокращает сессию.Я также установил maxIdleTimeout, но сеанс отбрасывается независимо.Для меня это выглядит так, как будто клиент (браузер) рассчитывает время сеанса и затем зависает.

Не знаю, как обойти это.

...