我正在java中构建一个具有基于jetty的嵌入式websocket服务器的应用程序。客户端是Google Chrome中的默认websocket实现。只有在连接关闭一定时间后服务器和客户端之间没有传输时,一切正常。 我不确定是谁关闭了连接:jetty服务器或chrome浏览器。
我认为解决这个问题的方法是每x秒发送一条消息,但我已经打开了更好的解决方案。
所以...我的问题是:
这是websocket协议所需要的东西,在这种情况下,Chrome浏览器正在关闭我的连接吗?
这是否与jetty相关并且或多或少与websocket协议有关?在这种情况下,如何在jetty中禁用它?
还有其他问题吗?
由于
更新:即使我发送1条消息/秒仍然关闭连接
答案 0 :(得分:37)
在回答您的第三个问题时:您的客户希望能够应对临时网络问题,例如:假设用户在休眠的会议之间关闭他们的笔记本电脑,或者网络暂时中断。
解决方案是监听Web套接字客户端上的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);
};
}
答案 1 :(得分:15)
您需要不时发送ping消息。我认为默认超时是300秒。 Sending websocket ping/pong frame from browser
答案 2 :(得分:9)
我找到了另一个相当快速和肮脏的解决方案。
如果您使用低级方法来实现WebSocket并且您自己实现onOpen
方法,则会收到实现WebSocket.Connection
接口的对象。此对象具有setMaxIdleTime方法,您可以调整该方法。
答案 3 :(得分:6)
您实际上可以使用WebSocketServletFactory实例在Jetty服务器端配置中设置超时间隔。例如:
WebSocketHandler wsHandler = new WebSocketHandler()
{
@Override
public void configure(WebSocketServletFactory factory)
{
factory.getPolicy().setIdleTimeout(1500);
factory.register(MyWebSocketAdapter.class);
...
}
}
答案 4 :(得分:4)
刚为自己找到了解决方案。您要设置的是WebSocketServlet的maxIdleTime,以毫秒为单位。如何做到这一点取决于你如何配置你的servlet。使用Guice ServletModule,您可以执行类似的操作,超时10小时:
serve("ws").with(MyWSServlet.class,
new HashMap<String, Sring>(){{ put("maxIdleTime", TimeUnit.HOURS.toMillis(10) + ""); }});
任何&lt; 0都是无限的空闲时间我相信。
答案 5 :(得分:3)
我相信这是一个Jetty问题。我没有看到任何浏览器由于不活动而关闭WebSocket连接,也没有遇到其他超出WebSocket连接的WebSocket服务器。
Jetty主要专注于构建基于HTTP的应用程序servlet。在这种情况下,需要非常积极地清理HTTP连接,并且HTTP不是为长期连接而设计的,因此具有短暂的默认超时是合理的。
我没有看到你描述的确切问题(甚至关闭活动)但我确实看到WebSocket连接在30秒不活动后关闭。有可能在旧版本的Jetty或当前版本中由于某些其他原因,计时器不会被WebSocket活动重置。我通过在BlockingChannelConnector对象上使用setMaxIdleTime方法将超时值设置为Integer MAX_VALUE来解决这个问题。
答案 6 :(得分:2)
我认为您遇到的超时实际上是TCP / IP的一部分,解决方案是偶尔发送空消息。
答案 7 :(得分:2)
这是一个关于如何使用WebSocketServlet配置Jetty的websocket超时(最可能的罪魁祸首)的示例(在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])
}
}
答案 8 :(得分:1)
我有类似的经历,我相信可能是浏览器缩短会议时间。我也设置了maxIdleTimeout,但无论如何都会丢弃会话。对我来说,它似乎是客户端(浏览器)超时会话然后挂断。
不知道如何解决它。
答案 9 :(得分:1)
由于@Doua Beri即使在发送频率为1 Hz的情况下也会关闭连接,因此可能是由于消息的大小限制造成的。
Spring的WebSockets这段话可能很有用,我强调...
尽管从理论上讲,WebSocket消息在 大小,实际上WebSocket服务器会施加限制-例如 8K 在Tomcat上使用64K,在Jetty上使用64K 。因此,STOMP客户端例如 stomp.js在16K边界处拆分较大的STOMP消息并将其发送 作为多个WebSocket消息,因此需要服务器进行缓冲和 重新组装。
答案 10 :(得分:0)
同一问题:在Java Server端将WebSockets和sockjs-client / 1.0.3 / sockjs库与@ServerEndPoint一起使用。 Websocket的连接不断变化。
我转而使用Stomp和sockJS(放弃@ServerEndpoint),但是遇到了另一个在SO上流行的问题-/ info = 34424-404错误-
我不得不放弃使用other中建议的Stomp Spring库的xml方法。我的项目中有Spring 4.2,许多SockJS Stomp实现通常可以与Spring Boot实现一起很好地工作。 This implementation from Baeldung起作用了(对我而言,没有从Spring 4.2更改为5)。
使用他的博客中提到的依赖项后,它仍然给我ClassNotFoundError。我添加了以下依赖项来修复它。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
答案 11 :(得分:0)
这对我有用,而其他解决方案却没有!
这不再需要一直连接到您的EC2实例。因此,即使由于互联网连接中断而导致连接松动,只要您获得新的wifi访问,它就会自动重新连接到正在运行的内核。
此外,别忘了在tmux帐户或ngnix或类似环境中启动jupyter。
希望这会有所帮助!