我正在用java构建一个应用程序,该应用程序具有基于jetty的嵌入式websocket服务器。客户端是googlechrome中默认的websocket实现。只有在连接关闭一段时间后服务器和客户端之间没有传输的情况下,一切都正常。我不确定是谁在关闭连接:jetty服务器还是chrome浏览器。
我认为解决这个问题的方法是每x秒发送一条消息,但我对更好的解决方案持开放态度。
所以。。。我的问题是:
-
这是websocket协议所要求的吗?在这种情况下,chrome浏览器正在关闭我的连接?
-
这是不是与码头更相关,或多或少与websocket协议有关?在这种情况下,如何在码头中禁用此功能?
-
还有其他问题吗??
感谢
更新:即使我每秒发送1条消息,连接仍然关闭
在回答您的第三个问题时:您的客户无论如何都希望能够处理临时网络问题,例如,假设用户在会议之间关闭笔记本电脑,使其休眠,或者网络只是暂时关闭。
解决方案是侦听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);
};
}
您需要不时发送ping消息。我认为默认超时是300秒。从浏览器发送websocket乒乓帧
我发现了另一个相当快速和肮脏的解决方案。如果您使用低级别方法来实现WebSocket,并且您自己实现onOpen
方法,则会收到一个实现WebSocket.Connection
接口的对象。这个对象有一个可以调整的setMaxIdleTime方法。
您实际上可以使用WebSocketServletFactory
实例在Jetty服务器端配置中设置超时间隔。例如:
WebSocketHandler wsHandler = new WebSocketHandler() {
@Override
public void configure(WebSocketServletFactory factory) {
factory.getPolicy().setIdleTimeout(1500);
factory.register(MyWebSocketAdapter.class);
...
}
}
我认为您遇到的这种超时实际上是TCP/IP的一部分,解决方案是偶尔发送一次空消息。
我自己刚刚找到了解决方案。您要设置的是WebSocketServlet的maxIdleTime,单位为毫秒。如何做到这一点取决于如何配置servlet。使用Guice Servlet模块,您可以在超时10小时时执行以下操作:
serve("ws").with(MyWSServlet.class,
new HashMap<String, Sring>(){{ put("maxIdleTime", TimeUnit.HOURS.toMillis(10) + ""); }});
任何<我相信0是无限的空闲时间。
我认为这是Jetty的问题。我没有看到任何浏览器由于不活动而关闭WebSocket连接,也没有遇到其他WebSocket服务器超时WebSocket的连接。
Jetty主要致力于构建基于HTTP的应用程序servlet。在这种情况下,HTTP连接需要非常积极地清理,并且HTTP不是为长寿命连接设计的,因此具有较短的默认超时是合理的。
我没有看到你描述的确切问题(即使有活动也会关闭),但我确实看到WebSocket连接在30秒不活动后关闭。在旧版本的Jetty或当前版本中,由于其他原因,WebSocket活动可能不会重置计时器。我通过在BlockingChannelConnector对象上使用setMaxIdleTime方法将超时值设置为Integer MAX_value来解决这个问题。
这里有一个关于如何使用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])
}
}
我也有类似的经历,我相信可能是浏览器缩短了会话。我还设置了maxIdleTimeout,但不管怎样,会话都会被丢弃。在我看来,似乎是客户端(浏览器)在超时会话,然后挂断了。
不知道如何解决这个问题。
由于@Doua-Beri即使在有1 Hz SEND的情况下也会遇到连接关闭,这可能是由于消息的大小限制。
这段来自Spring的WebSockets的文章可能很有用,我强调。。。
尽管理论上WebSocket消息在大小,在实践中WebSocket服务器会施加限制—例如,8KTomcat和Jetty上的64K。因此,STOMP客户如stomp.js在16K边界上拆分较大的stomp消息并发送作为多个WebSocket消息,因此需要服务器缓冲和重新组装。
同样的问题:使用WebSocket&sockjs-client/1.0.3/sockjs库,在Java服务器端带有@ServerEndPoint。websocket连接不断断开。
我转而使用Stomp和sockJS(放弃@ServerEndpoint),但在SO上遇到了另一个流行的问题-/info=34424-出现404错误-
我不得不放弃使用其他地方建议的Stomp-Spring库的xml方法。我的项目中有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>
这对我有效,而其他解决方案则不然!
- 更新您的jupyters
- 通过您喜欢的笔记本电脑或实验室启动您的jupyters,但在控制台的行末尾添加以下代码:<--无浏览器>
这需要一直连接到您的EC2实例。因此,即使你因互联网连接丢失而失去连接,只要你获得了新的wifi访问权限,它就会自动重新连接到活跃工作的内核。
此外,不要忘记在tmux帐户或ngnix或其他类似环境中启动您的jupyter。
希望这能有所帮助!