websocket自动关闭连接

时间:2012-01-29 19:44:04

标签: java javascript google-chrome jetty websocket

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

我认为解决这个问题的方法是每x秒发送一条消息,但我已经打开了更好的解决方案。

所以...我的问题是:

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

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

  3. 还有其他问题吗?

  4. 由于

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

12 个答案:

答案 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)

这对我有用,而其他解决方案却没有!

  1. 更新您的jupyters
  2. 通过您喜欢的笔记本或实验室启动jupyter,但在控制台的行末添加以下代码:<-no-browser>

这不再需要一直连接到您的EC2实例。因此,即使由于互联网连接中断而导致连接松动,只要您获得新的wifi访问,它就会自动重新连接到正在运行的内核。

此外,别忘了在tmux帐户或ngnix或类似环境中启动jupyter。

希望这会有所帮助!