We are developing a web application that will run only on modern browsers (IE10+) for different reasons.
One of the features we implemented is Socket.io 1.x. However, by default the Socket.io client tries to support older browsers, so it starts a connection with long polling and then updates that to WebSockets. This is a waste of time and resources, given we know for sure the browser supports WS.
I've searched around, and I can only find this wiki page which, however, is about Socket.io 0.9.
Eventually, I found the documentation for engine.io-client (on which Socket.io-client is based on the 1.x branch). This is the code that I wrote and seems to be working. However, I would like to know if it's correct or if I'm doing something wrong:
io.connect('https://...', { upgrade: false, transports: ['websocket'] })
Weirdly, just setting the transports
property to an array with websockets
only wasn't enough; I also had to disable upgrade
. Is this correct?
I made some new discoveries.
With transports
set to ['websocket']
only, it doesn't make any difference wether upgrade
is enabled or not. Is that normal?
First of all, every modern browser supports WebSockets these days. Socket.IO uses much more boilerplate code and resources to make it fall back to other technologies. Most of the time, you don't need this level of support. Even in terms of network traffic, Socket.IO is way more expensive.
Although Socket.IO indeed uses WebSocket for transport when possible, it adds additional metadata to each packet. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a plain WebSocket server either.
Avoid using WebSockets if only a small number of messages will be sent or if the messaging is very infrequent. Unless the client must quickly receive or act upon updates, maintaining the open connection may be an unnecessary waste of resources.
Websocket is created when you make upgrade from http to websocket, so it kind of does need http. socket.io isn't a pure Websocket server/implementation, it depends on HTTP for its initial connection setup.
However, by default the Socket.io client tries to support older browsers, so it starts a connection with long polling and then updates that to WebSockets. This is a waste of time and resources, given we know for sure the browser supports WS. I've searched around, and I can only find this wiki page which, however, is about Socket.io 0.9.
Check Run websocket only mode for Socket.IO #16 with "transports: ["polling"]" , you can see that the request-protocol is http. with "transports: ["websocket"], and the USING_STICKY_SESSION_SIO = true, you can see that the initial request is again "http" --> which is wrong! The initial request should already be "ws://" protocol.
Key features of Socket.IO: It helps in broadcasting to multiple sockets at a time and handles the connection transparently. It works on all platform, server or device ensuring the equality, reliability, and speed. It automatically upgrades the requirement to WebSocket if needed.
The third misconception is that Socket.IO downgrades the connection as a fallback on older browsers. It actually assumes that the browser is old and starts an AJAX connection to the server, that gets later upgraded on browsers supporting WebSocket, after some traffic is exchanged. See below for details.
There are two types of "upgrades" happening with socket.io. First (in socket.io 1.0+), socket.io starts all connections with an http polling request and it may actually exchange some initial data with just an http request. Then, at some point after that, it will try to actually initiate a webSocket connection. the webSocket connection is done by sending a particular type of http request that specifies an upgrade: websocket
header and the server can then respond appropriately whether it supports websocket or not. If the server agrees to the upgrade, then that particular http connection is "upgraded" to the webSocket protocol. At that point, the client then knows that webSocket is supported and it stops using the polling http requests, thus completing its upgrade
to webSocket.
You can prevent the initial http polling entirely by doing this on the client:
var socket = io({transports: ['websocket'], upgrade: false});
This will prevent polling connections from your own cooperating clients. If you want to prevent any clients from ever using polling, then you can add this to the server:
io.set('transports', ['websocket']);
But, if you set this on the server, socket.io clients that are initially connecting with http polling will not work at all. So, this should only be matched with the right settings in the client such that the client never starts with polling.
This will tell both ends that you only want to use webSockets and socket.io will skip the extra http polling at the beginning. Fair warning, doing this requires webSocket support so this rules out compatible with older versions of IE that didn't yet support webSocket. If you want to retain compatibility, then just let socket.io do it's thing with a couple http requests initially.
Here's more info on the protocol upgrade from http to webSocket.
The webSockets protocol initiates EVERY webSocket with an HTTP connection. That's the way all webSockets work. That HTTP connection contains some headers on it that indicate that the browser would "like" to upgrade to the webSockets protocol. If the server support that protocol, then it responds telling the client that it will upgrade to the webSocket protocol and that very socket then switches from the HTTP protocol to the webSocket protocol. This is how a webSocket connection is designed to work. So, the fact that you see your webSocket connection starting with an HTTP connection is 100% normal.
You can configure socket.io to NEVER use long polling if that makes you feel better, but this will not change the fact that the webSocket connection will still start with an HTTP connection that is then upgraded to the webSocket protocol and it will not improve the efficiency of operation in modern browsers that support webSockets. It will, however make it so that your connection will not work in older browsers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With