正确关闭WebSocket(HTML5,Javascript)


127

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

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

Answers:


110

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

为了干净地关闭连接,从一个对等方发送一个仅包含0xFF字节后跟0x00字节的帧,以要求另一对等方关闭连接。

如果要编写服务器,则应确保在服务器关闭客户端连接时发送关闭帧。常规的TCP套接字关闭方法有时可能会很慢,并且导致应用程序认为该连接仍处于打开状态,即使没有打开也是如此。

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

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

我不确定页面刷新后如何获得onclose事件。页面重新加载后,websocket对象(带有onclose处理函数)将不再存在。如果您在页面加载时立即尝试在页面上建立WebSocket连接,那么您可能会遇到这样的问题:服务器在旧连接断开后不久(新的浏览器未准备好)拒绝了新的连接以在您尝试连接的位置进行连接),并且您将获得新websocket对象的onclose事件。


2
在Firefox中,连接似乎可能会挂在下一页加载中。我找不到参考,但我认为可能存在错误。另一种可能性是onclose,当用户导航/页面重新加载时,事件被意外触发,或者有意触发。我已经发布了一个问题,询问预期的行为是什么,哪种浏览器正确,以及我们如何实现自动重新连接。
leggetter 2012年

4
考虑这些问题onbeforeunload事件
artkoenig

36

很简单,您将其关闭:)

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

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


35

事实是,当今有2个主要的WebSocket协议版本正在使用。使用[0x00][message][0xFF]协议的旧版本,然后使用Hybi格式的数据包的新版本。

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

但是,对于使用新协议版本的浏览器(例如Firefox,Chrome和最终的IE10),仅关闭浏览器将导致浏览器自动关闭连接。也就是说,如果刷新页面或浏览离开页面,浏览器不会自动关闭连接。但是,浏览器的作用是向服务器发送一个hybi数据包,其第一个字节(原型身份)为0x88(最好称为关闭数据帧)。服务器收到此数据包后,可以选择自行关闭连接。


4
服务器端的一个实际示例如何管理此hybi数据包?
albanx

9
无法关闭连接似乎很疯狂。WebSocket变量在页面重新加载时消失了,那么如果无法访问该连接,为什么会保持打开状态呢?重用连接也没有意义。
Triynko

@albanx在下面检查我的答案
artkoenig 2015年

任何代码示例都说明如何从websocket客户端(即浏览器)发送关闭帧。我正在使用ws npm模块
Shaik Syed Ali

3

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


1
就我而言,Connection在数据传输过程中已关闭,在Opera和iOS系列浏览器中效果很好。请帮帮我..自上个两周以来,我一直在努力解决这个问题。stackoverflow.com/q/30799814/2225439
Mrug 2015年

2

通过使用Web套接字的close方法,您可以根据需要编写任何函数。

var connection = new WebSocket('ws://127.0.0.1:1337');
    connection.onclose = () => {
            console.log('Web Socket Connection Closed');
        };
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.