Have some way to keep the same socket.io connection on client side if user open a new page or refresh the page, maybe store the socket in session or it's impossible?
It's impossible. You cannot keep the same socket.io or webSocket client connection when the page is changed or refreshed. The browser simply does not do that. When a new page is loaded or the current page is refreshed, all resources from the previous page are closed and freed by the browser, including socket.io/webSocket connections.
So, your server has to expect a new socket.io connection from the newly loaded page. If you use cookies or a server-side session object, you can identify, on the server, when a connection is coming from a client that you have previously seen and the server can then act accordingly to realize that this is just a previous client reconnecting on a new page.
It seems now that WebWorker are a more widespread technology that it could be use to share websocket.
As explain in this article https://crossbario.com/blog/Websocket-Persistent-Connections/
Webworker are Javascript that is running outside the "thread of the page" and thus are not deleted on page change.
Note that it is running only in the same domain.
You can also look at Kanaka's answer here How to maintain a WebSockets connection between pages? (2012-2017 answer beware)
Related
I've been implementing a WebSocket with JavaScript and I have this one problem:
The endpoint that my web-application is connected to doesn't send back a close control frame when I'm sending it one.
This isn't that bad because browsers close the WebSocket connection after a while.
But a few things to notice are:
Browsers do only allow a specific amount of WebSockets to be connected at the same time.
When refreshing the web-application a new WebSocket is created
This causes the problem on IE:
When refreshing the web-application more than 6 times, a WebSocket connection cannot be made.
It seems like IE doesn't "delete" the WebSockets if they haven't been closed cleanly. And what's odd is that the amount of web sockets never seems to decrease by refreshing or just by waiting.
Only by closing the browser window, or the tab resets the number of WebSockets to 0.
I've done some researching and this is what I've found out:
Browsers do only support a specific amount of WebSockets to be connected at the same time.
IE supports 6 websockets to be connected [link]
Chrome supports 255 websockets to be connected [link].
And socket.onclose() isn't triggered when you do socket.close(), it is called when the endpoint responses with a close message. [link]
IE waits 15 seconds for the endpoint to send the close message [link].
Chrome waits for 60s for the responding message [Sorry, no link for this, found this out by testing].
If no response message is received, the browser closes the WebSocket connection and a TimeoutError should occur.
Please correct me if I'm wrong :)
I've tried to use unbeforeload to disconnect from the endpoint in hope that the browser would close the connection after a while, but with no luck. [link].
It can also be the cause of that IE aren't able to do request inside the unbeforeload function [link].
Question:
Is there any way to reset the number of WebSockets that are
connected in the browser to the endpoint with JavaScript?
Is there a way to disconnect a WebSocket from the endpoint immediately without closing the connection cleanly?
Is the only way to get this to work to inform the ones who host their endpoint make some changes so they do send a closing frame back?
Is there anything I've misunderstood or that I could try to get this to work?
Here is (in my opinion) good documentation about the WebSocket protocols if somebody would like to read more about it [link1] [link2].
UPDATE:
Only by refreshing the web-application on IE the WebSockets don't get destroyed.
If you navigate between pages in the web-application a new WebSocket will be made but the last WebSocket will get destroyed.
If it is just an edge case problem, then using a http fallback might be your only option. I guess you already do this for proxy servers that block socket connection away.
There is just 1 idea to verify (unconfirmed). Unfortunately, don't have access to IE to verify.
Application may open websocket connection in WebWorker/iFrame. During page refresh, "websocket connection scope" will be deleted, and connection is freed
EXPLANATION
This content from the question body:
Only by refreshing the web-application on IE the WebSockets don't get destroyed. If you navigate between pages in the web-application a new WebSocket will be made but the last WebSocket will get destroyed.
Says that Websocket connection is not destroyed ONLY when page refreshes. During normal navigation, everything is OK.
So, if websocket connection is opened within other scope which will be deleted during page reload, then hopefully connection will be destroyed.
I use the javascript websocket to connect to the websocket server. I use python flask framework to navigate through webpages.
my project is as below:
the route "/" renders index.html page. In this page, I create a
websocket connection.
when I receive data from the server, I navigate to different route (for instance: "/page/1")
When i click on the href link on my index.html page, i see the websocket is being closed.
I googled out and implemented 2 methods of persistent storage.
LocalStorage
Shared Web Workers
Both of them were not of any use, since, the websockets are being closed when i click on the href link. From this I think that persistent storage of websocket instance is not a solution to my problem (please correct me if i am wrong). Please suggest me the right approach to tackle my problem. Thank you in advance.
I am using the latest version of google chrome (52.0.2743.82)
The WebSocket connection only persists as long as the page it was established for is open. Loading another page closes the WebSocket, so storing a reference to the object does not help (what it references no longer exists). You need to establish a new WebSocket connection after each page load.
(For an older look into how the problems here, see http://tavendo.com/blog/post/websocket-persistent-connections/, and 10.2.3 in the HTML spec https://html.spec.whatwg.org/multipage/workers.html#shared-workers-introduction)
I'm trying to "manipulate" an existing WebSocket connection of the browser.
For example: I visit the page example.com which creates a websocket connection with my browser.
Is there any way to access this connection and send data from javascript?
If you're trying to use your own Javascript to send data on a webSocket that the webpage's Javascript opened, then you will have to "hack" into the variables of the webpage to find how/where it stores the webSocket that it opened up. It would take some sleuthing through the site's Javascript to see how practical/possible that was. There is no "standard" way that a webSocket is stored in a page that allows you to just get it from there. You'd have to get it from the existing Javascript. If it's stored inside a closure, then it may not even be possible to get it from the console.
Or, you could just open your own webSocket to the page's server from the console and do whatever you wanted to do with your own webSocket using your own Javascript from there. You don't have to use the webSocket that the page opened as long as you can see from the Javascript in the page how it opens the webSocket and anything that might need to be sent in order to initialize the webSocket properly.
I would also suggest that you observe all applicable laws, licenses and terms of service.
I am using some comet techniques including long polling and forever frame. I am using iframes for cross subdomain stuff. The one issue that I ran into while implementing these techniques is when a user refreshes a page or navigates to another page causing a new request, the comet connection is kept open from the old page. My server (tornado) never receives a connection close and from my limited wireshark abilities I don't see any TCP fin packet sent. However, when I close the the browser, the sockets are closed at that point.
These abandoned open connections are just using up memory on the server side for no good reason. Also it causes problems when the server sends some message to the open socket and IE then correctly displays an error message: "Can't execute code from a freed script". So IE is trying to execute code on the old window which was navigated away from. How are other people handling this issue? Should I use onbeforeunload to somehow close the connection?
You could restart an open connection every now and then from the client side and if the request did not come in to the server in the specified time-frame you can safely close the old connection.
In my application, the client is a Javascript set of functions in the browser, and it does some work - for example, playing a clip.
It uses XmlHttpRequest to talk to the server.
However, the server is allowed to abruptly close the connection since there is no other way it seems, to interrupt the client.
Can the client detect, while it is playing the clip, that the connection was closed, and so print a message and erase the page?
Any help appreciated.
thanks,
Anil
If the clip is streamed to the client, you could just stop serving it.
However, it seems like the clip is being downloaded and then played through the browser. In this instance it's probably best to use a watchdog approach as described by CookieOfFortune: Poll the server regularly (once a second or so) and get it to respond with tiny message of confirmation. When the connection is closed, get the server to respond with a negative messgage.
Unfortunately, without using a comet-like system, it's very hard to get the server to 'send' a message indicating session closure.
Bear in mind though, that as soon as the client has downloaded a clip they will be able to play it in full if they want to. Unfortunately there's no way to stop this besides switching to a streaming approach. If securing your content is a priority, I'd suggest making this change.
You can probably poll the XmlHttpRequest object, so just try to send a heartbeat every once in a while to see if the connection is closed. Otherwise, the server would have to send some signal to tell the client it is going to close the connection.
It does seem that the server cannot notify the client that the connection is closed; however the polling method suggested is not as efficient as a notification would have been.
I solved it by specifying that at the NEXT Get request, the client would be told that its session is invalid.
This was implemented by URL rewriting - appending "jsessionid=[id]" on each request sent by the Javascript functions. the servlet stores the current session id.