【问题标题】:Closing WebSocket correctly (HTML5, Javascript)正确关闭 WebSocket (HTML5, Javascript)
【发布时间】:2024-01-21 06:30:01
【问题描述】:

我正在玩 HTML5 WebSockets。我想知道,如何优雅地关闭连接?比如,如果用户刷新页面,或者只是关闭浏览器会发生什么?

当用户只刷新页面而不调用 websocket.close() 时,会出现一种奇怪的行为 - 当他们在刷新后返回时,它会触发 websocket.onclose 事件。

【问题讨论】:

    标签: javascript sockets html websocket


    【解决方案1】:

    很简单,你关闭它:)

    var myWebSocket = new WebSocket("ws://example.org"); 
    myWebSocket.send("Hello Web Sockets!"); 
    myWebSocket.close();
    

    您是否还检查了following site 并检查了introduction article of Opera

    【讨论】:

      【解决方案2】:

      根据protocol specv76(目前支持的浏览器实现的版本):

      为了干净地关闭连接,一个帧只包含一个 0xFF 字节 后跟一个 0x00 字节从一个对等点发送以询问另一个对等点 关闭连接。

      如果您正在编写服务器,则应确保在服务器关闭客户端连接时发送关闭帧。正常的 TCP 套接字关闭方法有时会很慢,并导致应用程序认为连接仍然打开,即使它不是。

      当您关闭或重新加载页面时,浏览器确实应该为您执行此操作。但是,您可以通过捕获 beforeunload 事件来确保发送关闭帧:

      window.onbeforeunload = function() {
          websocket.onclose = function () {}; // disable onclose handler first
          websocket.close();
      };
      

      我不确定在刷新页面后如何获得 onclose 事件。一旦页面重新加载,websocket 对象(带有 onclose 处理程序)将不再存在。如果您在页面加载时立即尝试在页面上建立 WebSocket 连接,那么您可能会遇到一个问题,即服务器在旧连接断开后不久就拒绝新连接(或者浏览器尚未准备好在您尝试连接的点建立连接)并且您将获得新 websocket 对象的 onclose 事件。

      【讨论】:

      • 有可能在 Firefox 中连接似乎一直停留到下一页加载。我找不到参考,但我认为这可能存在错误。另一种可能性是onclose 事件被意外触发,或者可能是故意触发的,因为用户导航/页面重新加载。我已经posted a question 询问预期的行为应该是什么,哪个浏览器正确,以及我们如何实现自动重新连接。
      • 考虑 these problemsonbeforeunload 事件
      【解决方案3】:

      问题是目前使用的 WebSockets 有 2 个主要协议版本。旧版本使用[0x00][message][0xFF] 协议,新版本使用Hybi 格式数据包

      Opera 和 iPod/iPad/iPhone 使用旧协议版本,因此在 WebSockets 服务器中实现向后兼容性实际上很重要。在这些使用旧协议的浏览器中,我发现刷新页面、离开页面或关闭浏览器都会导致浏览器自动关闭连接。太好了!!

      但是对于使用新协议版本的浏览器(例如 Firefox、Chrome 和最终的 IE10),仅关闭浏览器会导致浏览器自动关闭连接。也就是说,如果你刷新页面,或者离开页面,浏览器不会自动关闭连接。然而,浏览器所做的是向服务器发送一个 hybi 数据包,其中第一个字节(proto ident)是0x88(更好地称为关闭数据帧)。一旦服务器收到这个数据包,它可以强制关闭连接本身,如果你愿意的话。

      【讨论】:

      • 一个实例在服务器端如何管理这个hybi包?
      • 它不关闭连接似乎很疯狂。 WebSocket 变量在页面重新加载时被清除,那么如果无法访问连接为什么会保持打开状态?重用连接也没有意义。
      • @albanx 在下面查看我的答案
      • 关于如何从 websocket 客户端(即浏览器)发送关闭帧的任何代码示例。我正在使用 ws npm 模块
      【解决方案4】:

      正如 theoobe 所述,某些浏览器不会自动关闭 websocket。不要尝试在客户端处理任何“关闭浏览器窗口”事件。如果您考虑支持主要的桌面 AND 移动浏览器(例如,onbeforeunload 在 Mobile Safari 中不起作用),目前没有可靠的方法来做到这一点。我在服务器端处理这个问题方面有很好的经验。例如。如果您使用 Java EE,请查看 javax.websocket.Endpoint,如果您关闭/重新加载浏览器窗口,将调用 OnClose 方法或 OnError 方法,具体取决于浏览器。

      【讨论】:

      • 在我的情况下,连接在数据传输期间关闭,它在 Opera 和 iOS 系列浏览器的情况下运行良好。请帮帮我。自上两周以来,我一直在与这个问题作斗争。 *.com/q/30799814/2225439
      【解决方案5】:

      通过使用web socket的close方法,你可以根据需要编写任何函数。

      var connection = new WebSocket('ws://127.0.0.1:1337');
          connection.onclose = () => {
                  console.log('Web Socket Connection Closed');
              };
      

      【讨论】:

        【解决方案6】:

        请用这个

        var uri = "ws://localhost:5000/ws";
        var socket = new WebSocket(uri);
        socket.onclose = function (e){
            console.log(connection closed);
        };
        window.addEventListener("unload", function () {
            if(socket.readyState == WebSocket.OPEN)
                socket.close();
        });
        

        关闭浏览器不会触发 websocket 关闭事件。您必须手动调用 socket.close()。

        【讨论】: