Closing WebSocket correctly (HTML5, Javascript)
I am playing around with HTML5 WebSockets. I was wondering, how do I close the connection gracefully? Like, what happens if user refreshes the page, or just closes the browser?
There is a weird behavior when a user just refresh the page without calling websocket.close()
- when开发者_开发知识库 they return after the refresh it will hit the websocket.onclose
event.
According to the protocol spec v76 (which is the version that browser with current support implement):
To close the connection cleanly, a frame consisting of just a 0xFF byte followed by a 0x00 byte is sent from one peer to ask that the other peer close the connection.
If you are writing a server, you should make sure to send a close frame when the server closes a client connection. The normal TCP socket close method can sometimes be slow and cause applications to think the connection is still open even when it's not.
The browser should really do this for you when you close or reload the page. However, you can make sure a close frame is sent by doing capturing the beforeunload event:
window.onbeforeunload = function() {
websocket.onclose = function () {}; // disable onclose handler first
websocket.close();
};
I'm not sure how you can be getting an onclose event after the page is refreshed. The websocket object (with the onclose handler) will no longer exist once the page reloads. If you are immediately trying to establish a WebSocket connection on your page as the page loads, then you may be running into an issue where the server is refusing a new connection so soon after the old one has disconnected (or the browser isn't ready to make connections at the point you are trying to connect) and you are getting an onclose event for the new websocket object.
The thing of it is there are 2 main protocol versions of WebSockets in use today. The old version which uses the [0x00][message][0xFF]
protocol, and then there's the new version using Hybi formatted packets.
The old protocol version is used by Opera and iPod/iPad/iPhones so it's actually important that backward compatibility is implemented in WebSockets servers. With these browsers using the old protocol, I discovered that refreshing the page, or navigating away from the page, or closing the browser, all result in the browser automatically closing the connection. Great!!
However with browsers using the new protocol version (eg. Firefox, Chrome and eventually IE10), only closing the browser will result in the browser automatically closing the connection. That is to say, if you refresh the page, or navigate away from the page, the browser does NOT automatically close the connection. However, what the browser does do, is send a hybi packet to the server with the first byte (the proto ident) being 0x88
(better known as the close data frame). Once the server receives this packet it can forcefully close the connection itself, if you so choose.
Very simple, you close it :)
var myWebSocket = new WebSocket("ws://example.org");
myWebSocket.send("Hello Web Sockets!");
myWebSocket.close();
Did you check also the following site And check the introduction article of Opera
As mentioned by theoobe, some browsers do not close the websockets automatically. Don't try to handle any "close browser window" events client-side. There is currently no reliable way to do it, if you consider support of major desktop AND mobile browsers (e.g. onbeforeunload
will not work in Mobile Safari). I had good experience with handling this problem server-side. E.g. if you use Java EE, take a look at javax.websocket.Endpoint, depending on the browser either the OnClose
method or the OnError
method will be called if you close/reload the browser window.
please use this
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();
});
Close browser doesn't trigger websocket close event. You must call socket.close()
manually.
By using close method of web socket, where you can write any function according to requirement.
var connection = new WebSocket('ws://127.0.0.1:1337');
connection.onclose = () => {
console.log('Web Socket Connection Closed');
};
The beforeunload
event should be avoided. From MDN:
Especially on mobile, the beforeunload event is not reliably fired.
Additionally, it should only be used for saving user data, not closing out a websocket connection.
Rather than closing the connection on beforeunload
, I would use the pagehide
or (fallback) unload
event, as the Chrome developer documentation suggests.
const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';
window.addEventListener(terminationEvent, (event) => {
if (event.persisted === false) {
// client is gone
socket.onclose = function () { };
socket.close();
}
});
Besides being recommended by the spec, the advantage of this approach is that you can still have a prompt confirming the user wants to leave (window.addEventListener("beforeunload", () => return "Are you sure?");
) without disconnecting the user if they choose to stay on the page.
As the Chrome docs say (emphasis added):
The document is still visible and the event is still cancelable at this point.
This could result in unintended closing of the websocket connection if the user doesn't actually leave the page.
精彩评论