正确关闭 WebSocket(HTML5、Javascript)

IT技术 javascript sockets html websocket
2021-03-13 23:39:36

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

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

6个回答

根据协议规范v76(这是当前支持的浏览器实现的版本):

为了干净地关闭连接,从一个对等方发送一个仅由 0xFF 字节和一个 0x00 字节组成的帧,以要求另一个对等方关闭连接。

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

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

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

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

有可能在 Firefox 中,连接似乎停留在下一个页面加载中。我找不到参考,但我认为这可能存在错误。另一种可能性是onclose当用户导航/页面重新加载时,事件被意外触发,或者可能是故意触发的。发布了一个问题,询问预期的行为应该是什么,哪个浏览器正确,以及我们如何实现自动重新连接。
2021-04-17 23:39:36
考虑这些问题onbeforeunload事件
2021-05-09 23:39:36

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

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

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

关于如何从 websocket 客户端(即浏览器)发送关闭帧的任何代码示例。我正在使用 ws npm module
2021-05-03 23:39:36
服务器端的一个实际例子如何管理这个hybi数据包?
2021-05-07 23:39:36
它没有关闭连接似乎很疯狂。WebSocket 变量在页面重新加载时被清除,那么如果无法访问连接,为什么它会保持打开状态?重用连接也没有意义。
2021-05-11 23:39:36
@albanx 在下面检查我的答案
2021-05-12 23:39:36

很简单,你关闭它:)

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

您是否还检查了以下站点并检查了Opera介绍文章

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

就我而言,连接在数据传输期间关闭,它在 Opera 和 iOS 系列浏览器的情况下运行良好。请帮帮我.. 自过去两周以来,我一直在与这个问题作斗争。stackoverflow.com/q/30799814/2225439
2021-04-19 23:39:36

请使用这个

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()。