Автоматическое закрытие соединения
Я создаю приложение в java, у которого есть встроенный сервер websocket, основанный на причале. Клиент - это реализация websocket по умолчанию в google chrome. Все работает нормально, только если между сервером и клиентом нет передачи через определенное время, соединение закрывается.
Я не уверен, кто закрывает соединение: сервер причала или браузер Chrome.
Решение этого, я думаю, - отправить сообщение каждые x секунд, но я открыт для лучших решений.
SO... мои вопросы:
-
Это то, что требует протокол websocket, и в этом случае браузер Chrome закрывает мое соединение?
-
Является ли это нечто более связанным с причалом и более или менее связано с протоколом websocket? В этом случае как отключить это в причале?
-
Есть ли другая проблема?
Спасибо
ОБНОВЛЕНИЕ: даже если я отправляю 1 сообщение в секунду, соединение закрывается
Ответы
Ответ 1
В ответ на третий вопрос: ваш клиент хочет в любом случае справиться с временными сетевыми проблемами, например. скажем, пользователь закрывает свой ноутбук между встречами, которые спящий с ним, или сеть просто временно отключается.
Решение состоит в том, чтобы прослушивать события 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);
};
}
Ответ 2
Вам нужно время от времени отправлять сообщения ping. Я думаю, что таймаут по умолчанию составляет 300 секунд.
Отправка веб-камеры ping/pong из браузера
Ответ 3
Я нашел другое, довольно быстрое и грязное решение.
Если вы используете низкоуровневый подход для реализации WebSocket и сами внедряете метод onOpen
, вы получаете объект, реализующий интерфейс WebSocket.Connection
. Этот объект имеет метод setMaxIdleTime, который вы можете настроить.
Ответ 4
Фактически вы можете установить интервал ожидания в конфигурации на стороне сервера Jetty, используя экземпляр WebSocketServletFactory
. Например:
WebSocketHandler wsHandler = new WebSocketHandler() {
@Override
public void configure(WebSocketServletFactory factory) {
factory.getPolicy().setIdleTimeout(1500);
factory.register(MyWebSocketAdapter.class);
...
}
}
Ответ 5
Просто нашел решение для себя. То, что вы хотите установить, - maxIdleTime для WebSocketServlet, в миллисекундах. Как это сделать, зависит от того, как вы настраиваете свой сервлет. С Guice ServletModule вы можете сделать что-то подобное для тайм-аута 10 часов:
serve("ws").with(MyWSServlet.class,
new HashMap<String, Sring>(){{ put("maxIdleTime", TimeUnit.HOURS.toMillis(10) + ""); }});
Все, что угодно и lt 0 - бесконечное время простоя, я полагаю.
Ответ 6
Я считаю, что это проблема Jetty. Я не видел, чтобы какие-либо браузеры закрывали соединения WebSocket из-за неактивности, и я не встречал других серверов WebSocket, которые не встречали соединения WebSocket.
Jetty (в основном) сосредоточен на создании сервлетов приложений на основе HTTP. В этом контексте HTTP-соединения должны быть очищены довольно агрессивно, а HTTP не предназначен для долговременных подключений, поэтому наличие короткого тайм-аута по умолчанию является разумным.
Я не видел точной проблемы, которую вы описали (закрытие даже с активностью), но я вижу, что соединения WebSocket закрываются через 30 секунд бездействия. Возможно, что в старых версиях Jetty или в текущей версии по какой-то другой причине таймер не является reset по активности WebSocket. Я обойду это, используя метод setMaxIdleTime на моем объекте BlockingChannelConnector, чтобы установить значение таймаута в Integer MAX_VALUE.
Ответ 7
Я думаю, что этот тайм-аут, который вы испытываете, на самом деле является частью TCP/IP, и решение состоит в том, чтобы просто отправлять пустые сообщения время от времени.
Ответ 8
Вот пример того, как настроить тайм-аут веб-сервера 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])
}
}
Ответ 9
У меня есть аналогичный опыт, и я считаю, что это может быть браузер, который сокращает сессию. Я также устанавливаю maxIdleTimeout, но сеанс отключается независимо. Для меня, похоже, что клиент (браузер) синхронизирует сеанс и затем вешает трубку.
Не знаю, как обойти это.
Ответ 10
Та же проблема: использовались WebSockets & Библиотека sockjs-client/1.0.3/sockjs с @ServerEndPoint на стороне Java-сервера. Соединения веб-сокетов продолжали разрываться.
Я перешел на использование Stomp и sockJS (отказавшись от @ServerEndpoint), но столкнулся с другой проблемой, популярной в SO -/info = 34424 - с ошибкой 404 -
Мне пришлось отказаться от использования XML-подхода библиотеки Stomp Spring, как это было предложено в других местах. В моем проекте Spring 4.2, и многие реализации SockJS Stomp обычно хорошо работают с реализациями Spring Boot. Эта реализация от Baeldung сработала (у меня без перехода с Spring 4.2 на 5).
После использования зависимостей, упомянутых в его блоге, он все равно дал мне ClassNotFoundError. Я добавил ниже зависимость, чтобы исправить это.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
Ответ 11
Это работало для меня, в то время как другие решения не были!
- Обновите свои юпитеры
- Запустите Jupyters через предпочитаемую тетрадь или лабораторию, но добавьте этот код в конце строки в консоли: & lt; - no-browser>
Это останавливает необходимость постоянного подключения к вашему экземпляру EC2. Поэтому, даже если вы потеряете соединение из-за потери интернет-соединения, всякий раз, когда вы получаете новый доступ к Wi-Fi, он автоматически повторно подключается к активно работающему ядру.
Кроме того, не забудьте запустить свой jupyter с учетной записью tmux или ngnix или в других подобных средах.
Надеюсь это поможет!