websocket自动关闭连接


77

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

我认为解决此问题的方法是每x秒发送一条消息,但是我愿意接受更好的解决方案。

所以...我的问题是:

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

  2. 这是与码头有关的更多东西,或多或少与websocket协议有关吗?在这种情况下,如何在码头上禁用它?

  3. 还有另一个问题吗?

谢谢

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


1
客户端和服务器之间是否有任何代理?众所周知,代理有时会关闭websocket(stackoverflow.com/questions/9017113/…
ndeverge 2012年

我正在使用Jetty,但我遇到了同样的问题。没有代理-我在本地主机上有一台服务器,而浏览器在同一台计算机上。
Ant Kutschera 2015年

嗯,您正在Internet Explorer上测试它吗?因为我仍然在痛苦关于这个奇怪的IE beahvior:connect.microsoft.com/IE/feedback/details/804653/...
塑料

Answers:


48

在回答您的第三个问题时:您的客户希望无论如何都能够解决临时的网络问题,例如,假设用户在两次会议之间将其休眠的计算机关闭,或者网络暂时中断了。

解决方案是侦听oncloseWeb套接字客户端上的事件,当事件发生时,设置客户端超时以重新打开连接,例如,一秒钟:

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


10

我找到了另一个相当快捷又肮脏的解决方案。如果您使用低级方法来实现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的一部分,解决方案是仅偶尔发送一次空消息。


1
嘿,谢谢..但这对我没有帮助。我刚尝试每秒发送1条消息,但连接仍在关闭
Doua Beri 2012年

大卫,你可以备份吗?我的理解是,TCP将诸如空闲超时之类的策略决策留给了应用程序,操作系统和网络基础结构(TCP试图与策略无关)。也许您正在考虑保持活动状态,这是周期性的消息,以确保连接没有静默终止(最终超时并通常在2小时后关闭连接)。
kanaka 2012年

@kanaka我在某处阅读过该内容,但我无法真正备份它。我可以肯定地知道,当我用Python编写自己的websocket服务器时,我发现需要不时发送一次空消息以防止其断开连接。
大卫·格雷森

这不是TCP / IP的一部分,但是可能是由于状态防火墙由于其空闲时间太长而丢失了连接状态的结果。您可能正在考虑解决此问题的TCP Keepalive。
David Hoelzer

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,但是无论如何会话都将被丢弃。对我来说,似乎是客户端(浏览器)使会话超时然后挂断。

不知道如何解决。


0

相同的问题:在Java Server端将WebSockets和sockjs-client / 1.0.3 / sockjs库与@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>

0

这对我有用,而其他解决方案则不行!

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

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

另外,不要忘记在tmux帐户或ngnix或类似环境中启动jupyter。

希望这可以帮助!


0

由于@Doua Beri即使在发送频率为1 Hz的情况下也处于关闭连接状态,因此它可能是由于消息的大小限制所致。

Spring的WebSockets的这一段可能很有用,我强调...

尽管从理论上讲WebSocket消息的大小几乎是无限的,但实际上WebSocket服务器会施加限制-例如,Tomcat 8K和Jetty 64K。因此,诸如stomp.js之类的STOMP客户端会在16K边界处分割较大的STOMP消息,并将其作为多个WebSocket消息发送,因此需要服务器进行缓冲和重新组装。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.