My app collects news and is fed by a websocket that periodically provides the data to show, the cadence of news is changeable and depends on when the vendors emit them.
When the app is opened in Internet Explorer, if no new items are received, the connection is stopped suddenly after about 20 seconds.
By doing some research I managed to bring the problem back to this specific Internet Explorer behavior:
https://connect.microsoft.com/IE/feedback/details/804653/rfc6455-websocket-pong-frame
In practice I found that IE sends Pong control frames, but if it does not receive a Ping response, it closes the connection.
Unfortunately I can not change anything server side to handle this unsolicited message, I was wondering if there is a way to handle this abnormal IE behavior from inside my app.
It seems that the issue happend only if the webSocket remain in idle state for more than 20 secs. We simply raised the frequency of heartbeat messages from the server up to 1 message every 10 secs and the issue never happened again
Related
I am using Server Sent Events for my small chat application, and I am storing a list of sent events on my server, along with passing an id field with SSE message.
Server Sent Events apparently has a concept of automatic reconnection, but I cannot seem to find a single instance where this actually occurs in practice.
For example, if you are on Android and tab out of the application, wait 30 seconds, and then tab back in, then the connection is broken. But the onerror event never occurs, and the readyState stays OPEN. So the only option to handle this situation seems to poll for heartbeats and do a manual reconnection by re-initializing the EventSource object if curr_time - last_heartbeat > heartbeat_interval
Another instance of disconnection is when you for example disable WiFI and then re-enable it. However, when this occurs, Android Chrome just automatically refreshes the page, so reconnection doesn't occur here either (instead it's just refresh which causes a disconnect and then a fresh connection).
So, am I missing something? SSE is touted as being very robust for its automatic reconnection ability, but I cannot find a single case where it actually performs a reconnection. What instances are there where a reconnection can actually occur, such that I can test this behavior?
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'm working on a website where some events are broadcasted to the clients using SSE (EventSource API). When testing my site on the mobile version of Chrome for Android, I noticed the connection is lost when the channel is idle for about five minutes.
I used several Android devices, with different carriers and different browsers and the result is the same, no matter if the screen is on or off. Desktop Chrome seems to keep the connection alive for a longer time.
Couldn't find any info about this, and when trying to debug the issue, all I got was a TCP "FIN" packet received from the telephone IP address about 3 and a half minutes after the last event was sent.
EventSource's onerror event doesn't get fired so I can't know when the connection was dropped to initiate a new one.
Is there any way to avoid this problem or should I just send some fake message every 30 secs to prevent connection idling?
Thanks in advance
Your connection was probably taken by a "push proxy" - a feature that is designed to improve battery life in phones.
Quote from "https://html.spec.whatwg.org/multipage/server-sent-events.html":
User agents running in controlled environments, e.g. browsers on
mobile handsets tied to specific carriers, may offload the management
of the connection to a proxy on the network. In such a situation, the
user agent for the purposes of conformance is considered to include
both the handset software and the network proxy.
For example, a browser on a mobile device, after having established a
connection, might detect that it is on a supporting network and
request that a proxy server on the network take over the management of
the connection. The timeline for such a situation might be as follows:
Browser connects to a remote HTTP server and requests the resource specified by the author in the EventSource constructor.
The server sends occasional messages.
In between two messages, the browser detects that it is idle except for the network activity involved in keeping the TCP connection alive,
and decides to switch to sleep mode to save power.
The browser disconnects from the server.
The browser contacts a service on the network, and requests that the service, a "push proxy", maintain the connection instead.
The "push proxy" service contacts the remote HTTP server and requests the resource specified by the author in the EventSource
constructor (possibly including a Last-Event-ID HTTP header, etc).
The browser allows the mobile device to go to sleep.
The server sends another message.
The "push proxy" service uses a technology such as OMA push to convey the event to the mobile device, which wakes only enough to
process the event and then returns to sleep.
This can reduce the total data usage, and can therefore result in
considerable power savings.
You can set the retry field to establish the reconnection time of EventSource instance
If the field name is "retry"
If the field value consists of only ASCII digits, then interpret the field value as an integer in base ten, and set the event stream's
reconnection time to that integer. Otherwise, ignore the field.
Here's the scenario, I have a client side application, served by PHP on a different server to the node.js + socket.io application. It can connect and receive broadcasts sent from the server. If the connection drops, the application falls back to polling a database (using setInterval()). It attempts to reconnect every 5 polls, and it can successfully reconnect and continue to receive messages.
My problem occurs when the user loads the page and the node server cannot be reached (I turned it off for testing), I then turn on the server and on the 5th poll, it successfully connects to the server, using socket.socket.reconnect();. However, whenever the server broadcasts messages, it doesn't fire the event. Note that this doesn't happen when testing on a phone (which falls back to a different socket method)
I have already seen the question found here Reconnection in socket.io problem in `socket.on('message',function(){})`, however, the socket has not previously been connected so I don't think it could be the session?
EDIT: I changed the socket.socket.reconnect() to socket.socket.connect() and it fixed the problem. If someone could explain the reasons of why this works I'd like to know. I know its because the server isn't actually reconnecting, but would like more info.
Thanks.
well you possibly know the reason for this. server is not reconnecting. it is actually connecting. when you tell socket.io to reconnect it searches for the previous connection handle and thats where the problem arises.
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.