Difference Between Web Sockets and Socket.IO



Good day, friends!

Web sockets and Socket.IO are probably the two most common means of real-time communication (hereinafter referred to as live communication). But how do they differ?

When building an application for live communication, there comes a time when you need to choose a tool for exchanging data between the client and server. Web sockets and Socket.IO are the most popular means of live communication on the modern web. Which one to choose? What is the difference between these technologies? Let's find out.

Web sockets


Speaking of web sockets, we mean the web communication protocol, which represents a full-duplex communication channel over a simple TCP connection. Simply put, this technology allows you to establish communication between the client and the server with minimal cost, allowing you to create applications that use all the advantages of live communication.

For example, imagine you are creating a chat: you need to receive and send data as quickly as possible, right? Web sockets do just fine with this! You can open a TCP connection and keep it open for as long as necessary.

Web sockets appeared in 2010 in Google Chrome 4, the first RFC ( 6455 ) was published in 2011.

Web sockets are used in the following cases:

  • Chats
  • Multiplayer games
  • Collaborative editing
  • Social (news) feeds
  • Location Based Applications

etc.

Socket.io


Socket.IO is a JavaScript library based (written on top) on web sockets ... and other technologies. It uses web sockets when available, or technologies such as Flash Socket, AJAX Long Polling, AJAX Multipart Stream, when web sockets are not available. An easy analogy is the comparison of the Fetch API and Axios.

Difference Between Web Sockets and Socket.IO


The main advantages of Socket.IO are the following:

  • -, Socket.IO . , . . -, .
  • - . Socket.IO .
  • , Socket.IO () .
  • Socket.IO .
  • Socket.IO .

It might seem that Socket.IO is the best tool for live communication. However, there are several situations where it is better to use web sockets.

Firstly, web sockets are supported by all modern browsers. Therefore, you rarely need the support of other technologies provided by Socket.IO.

If we talk about network traffic, then web sockets send only two requests:

  • GET to get HTML page
  • UPGRADE for connecting to web sockets

This allows you to connect to the server. What about Socket.IO?

  • GET to get HTML page
  • Socket.IO Client Library ( 207kb )
  • Three long polling Ajax requests
  • UPGRADE for connecting to web sockets

In the world of JS, 207kb is a lot. What an irrational use of network traffic!

In npm there is a package “websocket-vs-socket.io” that allows you to compare the network traffic of these technologies:

Web Socket Network Traffic:




Socket.IO Network Traffic:




The difference is obvious!

Writing a code


Simple web socket server


In our program on Node.js, we will create a server running on port 3001. Each time the client connects, we will assign it a unique ID. When sending a message to the client, we will notify him of the success: [<client-id>]: <message>

const WebSocket = require('ws')
const UUID = require('uuid')
const wss = new WebSocket.Server({ port: 3001 })

wss.on('connection', ws => {
  ws.id = UUID()

  ws.on('message', message => {
    ws.send(`[${ws.id}]: ${message}`)
  })
})

Fine! But what if we want to send a message to each connected client? Web sockets do not support mailing by default. This can be implemented as follows:

const WebSocket = require("ws")
const UUID      = require("uuid")
const wss       = new WebSocket.Server({ port: 3001 })

function broadcast(clientId, message) {
  wss.clients.forEach(client => {
    if(client.readyState === WebSocket.OPEN) {
      client.send(`[${clientId}]: ${message}`)
    }
  })
}

wss.on('conection', ws => {
  ws.id = UUID()
  ws.on('message', message => broadcast(ws.id, message))
})

Simply and easily! As you can see, WebSocket.Server keeps records of each connected client, so we can iterate and send a message to everyone. You can test the code on a computer (MacOS) or in a browser (Chrome) .

Simple server on Socket.IO


It was not difficult. Can Socket.IO make it even easier? How do we write the same server on Socket.IO?

const io = require('socket.io')
const server = io.listen(3002)

server.on('connection', socket => {
  socket.on('message', message => {
    socket.emit(`[${socket.id}]: ${message}`)
    socket.broadcast.emit(`[${socket.id}]: ${message}`)
  })
})

The code is almost half shorter! As you can see, the broadcast method does not send a notification to the sender, so we are forced to do this manually.

There is a problem: the code cannot be tested on a regular web socket client. This is due to the fact that, as noted earlier, Socket.IO does not use pure web sockets, but many technologies to support all possible clients. So how do we test its performance?

// head
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2.3.0/dist/socket.io.slim.js"></script>

// body
<script>
  ioClient = io.connect('http://localhost:3002')
  ioClient.on('connect', socket => {
    ioClient.send('hello world')
    ioClient.on('message', msg => console.log(msg))
  })
</script>

You must use a special client. In the above example, we load it from the CDN. This client allows us to conduct quick (dirty) tests in the browser.

As you can see, our examples are not much different. However, if we talk about compatibility, it should be remembered that Socket.IO works with its own library and cannot be used for purposes not related to web development. At the same time, web sockets can be used to solve a wide range of tasks, such as P2P communication, real-time data exchange between servers, etc.

On a note


Horizontal scaling. Let's say your chat has gained popularity and you need to add another server and load balancer to process requests. Well, if you open the connection to “server 1”, then the balancer switches you to “server 2”, you will get the error: “Error during WebSocket handshake: Unexpected response code: 400”. Socket.IO solves this problem by using cookies (or by routing connections based on source addresses), and web sockets do not have such a mechanism.
Performance. As noted earlier, Socket.IO provides several abstract layers above the transport layer of web sockets. Also, packing data into JSON format is used here, so there is no possibility to send binary data to the server (and vice versa). If you need such functionality, you have to “conjure” the library code in order to ensure the desired behavior. With web sockets such problems do not arise.

So what to choose?


You decide.

Socket.IO makes life easier, you don’t need to worry about problems related to load balancing, disconnection or sending messages ... but do you need such functionality? The Socket.IO client library weighs more than the React, Redux, and React-Redux packages combined. Are you sure you can’t limit yourself to web sockets?

Another important thing to keep in mind is that when using Socket.IO on the server side, most of the code will be written on the abstractions provided by this library. If you need to rewrite Node.js microservices in Go, Elixir, Java or another programming language, you will have to rewrite almost all the logic. For example, to send messages to Socket.IO, the “broadcast” method is used (which is implemented manually on web sockets), so when refactoring you will have to understand how this method works. Web sockets should be preferred in this case, as they are easier to adapt.

Thank you for attention.

All Articles