What is Socket.IO?
Socket.IO is an open-source cross-platform library that provides full-duplex bidirectional communication between a client and a server based on events. It is built on top of the WebSocket protocol providing additional capabilities such as automatic reconnection and fallback to HTTP long-polling where WebSockets cannot be used.
Socket.IO allows you to implement a wide variety of applications that depend on message exchange, for example, instant messaging, multi-user collaboration, real-time analytics, file-sharing, and notifications.
Similarities with WebSockets
Whilst Socket.IO is explicitly not a WebSocket implementation, there are several similarities. Both are event-based, meaning you would ‘listen’ for events like connect, disconnect or new_message and both allow you to send structured data like JSON objects.
You can think of Socket.IO as an abstraction layer on top of the underlying transport protocol. As well as the underlying communication layer, the library implements additional features such as automatic reconnection, packet buffering, and message acknowledgment as well as falling back to HTTP long-polling if WebSockets are unavailable, adding robustness.
Basic Example of Socket.IO
How does Socket.IO work?
The library supports two transportation methods: HTTP long-polling and WebSockets. The HTTP long-poll connection is established first and then upgraded to a WebSocket connection if possible. WebSockets cannot run everywhere, for example, they are blocked by many corporate proxies and firewalls, therefore the HTTP long-poll is initiated first since it is more likely to succeed. After the HTTP long-poll connection is established, it is ‘upgraded’ to a WebSocket connection in a process that is entirely transparent to the end user.
What is Socket.IO's architecture?
Socket.IO consists of two distinct layers, present on both the client and server:
The low-level plumbing is provided by a separate library called Engine.IO
The high-level API which is provided by Socket.IO
As a developer or user, you would not typically interface directly with Engine.IO but this is running behind the scenes to establish the connection, negotiate a transport mechanism and detect any disconnects. When comparing Engine.IO with WebSockets the two are functionally very similar, only Engine.IO provides an abstraction layer allowing you to migrate from a HTTP long-polling connection without (crucially) losing any messages.
The high-level Socket.IO API adds some noteworthy features on top of the basic connectivity provided by Engine.IO:
Buffered events allow you to send events when not connected that will be delivered when the client reconnects. This can lead to spikes in traffic if the client takes a long time to reconnect so you need to code your client accordingly.
Acknowledgments allow you to specify a callback which will be invoked when the other side acknowledges the message has been received.
Broadcasting and multicasting (a concept Socket.IO refers to as Rooms) allow a server to send a message to multiple clients, though a client can't broadcast to other clients.
What are the challenges when delivering a Socket.IO solution?
As with any solution that involves listening for and sending messages the biggest challenge is how to scale beyond a few thousand users.
Socket.IO is a library, it is NOT an infrastructure. As a solution architect or developer, you are responsible for deciding how your solution will reliably scale which is going to involve using multiple server nodes and load-balancing client connections between them. Load balancing comes with its own set of challenges but since Socket.io has been around for over a decade the community has come up with a robust set of best practices, for example, the concept of Adapters allows you to send a broadcast message between clients connected to different servers using a Pub/Sub mechanism.
Still, even though solutions do exist to scale Socket.IO, a lot of consideration is required by your development team and it is very difficult to consider every edge case. In contrast, PubNub provides a highly-scalable, low-latency messaging solution for teams looking to reach production quickly.
Suggested architecture for broadcasting messages across server instances with Socket.IO: