websocket自动关闭连接

问题描述 投票:66回答:10

我正在用Java构建具有基于码头的嵌入式websocket服务器的应用程序。客户端是google chrome中的默认websocket实现。只有在关闭连接一段时间后服务器和客户端之间没有传输,一切都可以正常进行。我不确定是谁关闭了连接:码头服务器或Chrome浏览器。

我认为解决方案是每x秒发送一条消息,但我愿意寻求更好的解决方案。

所以...我的问题是:

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

  2. 这是否与跳船相关并且与websocket协议或多或少有关?在这种情况下,如何在码头上禁用它?

  3. 还有其他问题吗?

感谢

更新:即使我每秒发送1条消息,连接仍然关闭

java javascript google-chrome jetty websocket
10个回答
38
投票

回答您的第三个问题:无论如何,您的客户都希望能够解决临时的网络问题。假设用户在两次会议之间关闭笔记本电脑以使其休眠,或者网络只是暂时关闭。

解决方案是在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);
    };
}

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>

15
投票

您需要不时发送ping消息。我认为默认超时是300秒。Sending websocket ping/pong frame from browser


9
投票

我找到了另一个相当快捷和肮脏的解决方案。如果您使用低级方法来实现WebSocket,并且您自己实现了onOpen方法,则会收到一个实现WebSocket.Connection接口的对象。该对象具有可以调整的setMaxIdleTime方法。


7
投票

您实际上可以使用WebSocketServletFactory实例在Jetty服务器端配置中设置超时间隔。例如:

        WebSocketHandler wsHandler = new WebSocketHandler()
        {
            @Override
            public void configure(WebSocketServletFactory factory)
            {
                factory.getPolicy().setIdleTimeout(1500);
                factory.register(MyWebSocketAdapter.class);
                ...
            }
        }

4
投票

只是为自己找到了解决方案。您要设置的是WebSocketServlet的maxIdleTime(以毫秒为单位)。如何执行取决于您如何配置servlet。使用Guice ServletModule,您可以在10小时的超时时间内执行以下操作:

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

任何<0,我相信都是无限的空闲时间。


3
投票

我相信这是一个码头问题。我没有看到任何浏览器由于不活动而关闭WebSocket连接,也没有遇到其他WebSocket服务器超时的WebSocket连接。

Jetty主要致力于构建基于HTTP的应用程序servlet。在这种情况下,需要非常积极地清理HTTP连接,并且HTTP不是为长期连接而设计的,因此具有较短的默认超时是合理的。

我没有看到您描述的确切问题(即使活动关闭也无法关闭),但我确实看到WebSocket连接在闲置30秒后关闭。可能是由于某些其他原因,在旧版本的Jetty或当前版本中,WebSocket活动未重置计时器。我通过在BlockingChannelConnector对象上使用setMaxIdleTime方法将超时值设置为Integer MAX_VALUE来解决此问题。


2
投票

我认为您遇到的这个超时实际上是TCP / IP的一部分,解决方案是只偶尔发送一次空消息。


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])
  }
}

1
投票

我有类似的经历,我相信可能是浏览器缩短了会话时间。我还设置了maxIdleTimeout,但是无论如何会话都将被丢弃。对我来说,似乎是客户端(浏览器)使会话超时,然后挂断。

不知道如何解决。

© www.soinside.com 2019 - 2024. All rights reserved.