【问题标题】:websocket closing connection automatically [closed]websocket自动关闭连接[关闭]
【发布时间】:2012-02-21 19:00:19
【问题描述】:

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

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

所以...我的问题是:

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

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

  3. 还有其他问题吗?

谢谢

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

【问题讨论】:

标签: java javascript google-chrome jetty 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);
    };
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

          • 嘿,谢谢.. 但这对我没有帮助。我刚刚尝试每秒发送 1 条消息,但连接仍在关闭
          • 大卫,你能备份一下吗?我的理解是,TCP 将诸如空闲超时之类的策略决策留给应用程序、操作系统和网络基础设施(TCP 试图与策略无关)。也许您正在考虑 keep-alive,它是定期消息,以确保连接没有静默终止(最终超时并通常在 2 小时后关闭连接)。
          • @kanaka 我在某处读到过,但我无法真正支持它。我肯定知道,当我用 Python 编写自己的 websocket 服务器时,我发现我需要偶尔发送一条空消息以防止它断开连接。
          • 这不是 TCP/IP 的一部分,但可能是状态防火墙由于空闲时间过长而丢失连接状态的结果。很可能,您正在考虑解决此问题的 TCP Keepalives。
          【解决方案6】:

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

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

          我相信任何

          【讨论】:

            【解决方案7】:

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

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

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

            【讨论】:

              【解决方案8】:

              这是一个关于如何使用 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])
                }
              }
              

              【讨论】:

                【解决方案9】:

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

                不知道怎么解决。

                【讨论】:

                  【解决方案10】:

                  由于@Doua Beri 即使有 1 Hz 的 SEND 也会遇到连接关闭,这可能是由于消息的大小限制

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

                  虽然理论上 WebSocket 消息在 大小,实际上 WebSocket 服务器会施加限制 — 例如,8K 在 Tomcat 上,在 Jetty 上 64K。出于这个原因,STOMP 客户如 stomp.js 在 16K 边界处拆分较大的 STOMP 消息并发送它们 作为多个 WebSocket 消息,因此需要服务器缓冲和 重新组装。

                  【讨论】:

                    【解决方案11】:

                    同样的问题:在 Java 服务器端使用带有 @ServerEndPoint 的 WebSockets 和 sockjs-client/1.0.3/sockjs 库。 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>
                    

                    【讨论】:

                      【解决方案12】:

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

                      1. 更新您的 jupyters
                      2. 通过您首选的笔记本或实验室启动您的 jupyter,但在控制台的行尾添加以下代码:

                      这不再需要一直连接到您的 EC2 实例。因此,即使由于 Internet 连接丢失而导致连接断开,每当您获得新的 wifi 访问权限时,它都会自动重新连接到正在运行的内核。

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

                      希望这会有所帮助!

                      【讨论】:

                        猜你喜欢
                        • 2023-03-03
                        • 2020-08-10
                        • 1970-01-01
                        • 2019-10-22
                        • 2012-08-08
                        • 2021-10-30
                        • 2016-05-15
                        • 1970-01-01
                        • 2016-12-08
                        相关资源
                        最近更新 更多