2011-01-27 305 views
93

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

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

回答

70

按照protocol spec V76(这是该浏览器当前支持实施的版本) :

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

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

当你关闭或重新加载页面时,浏览器应该为你做这些事情。但是,你可以确保一个紧密框架做捕获beforeunload事件发送:

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

我不知道如何可以刷新页面后会得到onClose事件会。一旦页面重新加载,websocket对象(使用onclose处理程序)将不再存在。如果您在页面加载时立即尝试在页面上建立WebSocket连接,那么您可能会遇到服务器在旧连接断开后很快拒绝新连接的问题(或者浏览器尚未准备就绪在你尝试连接的地方建立连接),并且你得到了一个新的websocket对象的onclose事件。

+1

这可能是在Firefox中,连接似乎流连进入下一个页面加载。我找不到参考,但我认为可能有一个关于此的错误。另一种可能性是`onclose`事件被意外触发,或者可能是故意的,因为用户导航/页面被重新加载。我[张贴的问题(http://stackoverflow.com/questions/10965720/should-websocket-onclose-be-triggered-by-user-navigation-or-refresh),询问预期的行为应该是什么,这浏览器是否正确以及如何实现自动重新连接。 – leggetter 2012-06-10 01:10:28

+3

考虑[这些问题](http://stackoverflow.com/questions/14645011/window-onbeforeunload-and-window-onunload-is-not-working-in-firefox-safari-o)用`onbeforeunload`事件 – artkoenig 2015-01-16 21:06:05

31

事情就是今天使用的WebSocket有两个主要协议版本。使用[0x00][message][0xFF]协议的旧版本,然后是使用Hybi格式化数据包的新版本。

Opera和iPod/iPad/iPhone使用旧协议版本,所以在WebSockets服务器中实现向后兼容性非常重要。使用这些浏览器使用旧协议时,我发现刷新页面或从页面导航或关闭浏览器都会导致浏览器自动关闭连接。大!!

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

+3

一个在服务器端如何管理这个hybi包的实际例子? – albanx 2013-01-09 07:03:10

2

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