websocket自动关闭连接

websocket closing connection automatically

本文关键字:连接 websocket      更新时间:2023-09-26

我正在用java构建一个应用程序,该应用程序具有基于jetty的嵌入式websocket服务器。客户端是googlechrome中默认的websocket实现。只有在连接关闭一段时间后服务器和客户端之间没有传输的情况下,一切都正常。我不确定是谁在关闭连接:jetty服务器还是chrome浏览器。

我认为解决这个问题的方法是每x秒发送一条消息,但我对更好的解决方案持开放态度。

所以。。。我的问题是:

  1. 这是websocket协议所要求的吗?在这种情况下,chrome浏览器正在关闭我的连接?

  2. 这是不是与码头更相关,或多或少与websocket协议有关?在这种情况下,如何在码头中禁用此功能?

  3. 还有其他问题吗??

感谢

更新:即使我每秒发送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>

这对我有效,而其他解决方案则不然!

  1. 更新您的jupyters
  2. 通过您喜欢的笔记本电脑或实验室启动您的jupyters,但在控制台的行末尾添加以下代码:&lt--无浏览器>

这需要一直连接到您的EC2实例。因此,即使你因互联网连接丢失而失去连接,只要你获得了新的wifi访问权限,它就会自动重新连接到活跃工作的内核。

此外,不要忘记在tmux帐户或ngnix或其他类似环境中启动您的jupyter。

希望这能有所帮助!