我在玩 HTML5 WebSockets。我想知道,如何优雅地关闭连接?比如,如果用户刷新页面或关闭浏览器会发生什么?
当用户在没有调用的情况下刷新页面时会出现一种奇怪的行为websocket.close()
- 当他们在刷新后返回时,它会触发websocket.onclose
事件。
我在玩 HTML5 WebSockets。我想知道,如何优雅地关闭连接?比如,如果用户刷新页面或关闭浏览器会发生什么?
当用户在没有调用的情况下刷新页面时会出现一种奇怪的行为websocket.close()
- 当他们在刷新后返回时,它会触发websocket.onclose
事件。
根据协议规范v76(这是当前支持的浏览器实现的版本):
为了干净地关闭连接,从一个对等方发送一个仅由 0xFF 字节和一个 0x00 字节组成的帧,以要求另一个对等方关闭连接。
如果您正在编写服务器,则应确保在服务器关闭客户端连接时发送关闭帧。正常的 TCP 套接字关闭方法有时会很慢,并导致应用程序认为连接仍然打开,即使它没有打开。
当您关闭或重新加载页面时,浏览器应该真正为您执行此操作。但是,您可以通过捕获 beforeunload 事件来确保发送关闭帧:
window.onbeforeunload = function() {
websocket.onclose = function () {}; // disable onclose handler first
websocket.close();
};
我不确定页面刷新后如何获得 onclose 事件。一旦页面重新加载,websocket 对象(带有 onclose 处理程序)将不再存在。如果您在页面加载时立即尝试在您的页面上建立 WebSocket 连接,那么您可能会遇到一个问题,即服务器在旧连接断开后很快拒绝新连接(或浏览器未准备好)在您尝试连接时建立连接)并且您将收到新 websocket 对象的 onclose 事件。
问题是目前使用的 WebSockets 有 2 个主要协议版本。使用[0x00][message][0xFF]
协议的旧版本,然后是使用混合格式数据包的新版本。
Opera 和 iPod/iPad/iPhone 使用旧协议版本,因此在 WebSockets 服务器中实现向后兼容性实际上很重要。在这些使用旧协议的浏览器中,我发现刷新页面,或离开页面,或关闭浏览器,都会导致浏览器自动关闭连接。伟大的!!
但是,对于使用新协议版本的浏览器(例如 Firefox、Chrome 和最终的 IE10),只有关闭浏览器才会导致浏览器自动关闭连接。也就是说,如果您刷新页面或离开页面,浏览器不会自动关闭连接。然而,浏览器所做的是向服务器发送一个 hybi 数据包,其中第一个字节(原型标识)是0x88
(更好地称为关闭数据帧)。一旦服务器收到这个数据包,它可以强制关闭连接本身,如果你愿意的话。
正如theoobe所提到的,某些浏览器不会自动关闭 websocket。不要尝试在客户端处理任何“关闭浏览器窗口”事件。如果您考虑支持主要的桌面和移动浏览器(例如onbeforeunload
在 Mobile Safari 中不起作用),目前没有可靠的方法可以做到这一点。我在服务器端处理这个问题方面有很好的经验。例如,如果您使用 Java EE,请查看javax.websocket.Endpoint,这取决于浏览器,如果您关闭/重新加载浏览器窗口,将调用该OnClose
方法或OnError
方法。
请使用这个
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()。