Différence entre les sockets Web et Socket.IO



Bonjour mes amis!

Les sockets Web et Socket.IO sont probablement les deux moyens de communication en temps réel les plus courants (ci-après dénommés communication en direct). Mais en quoi diffèrent-ils?

Lors de la création d'une application de communication en direct, il arrive un moment où vous devez choisir un outil pour échanger des données entre le client et le serveur. Les sockets Web et Socket.IO sont les moyens de communication en direct les plus populaires sur le Web moderne. Lequel choisir? Quelle est la différence entre ces technologies? Découvrons-le.

Prises Web


Parlant de sockets Web, nous entendons le protocole de communication Web, qui représente un canal de communication en duplex intégral sur une simple connexion TCP. En termes simples, cette technologie vous permet d'établir une communication entre le client et le serveur à un coût minimal, vous permettant de créer des applications qui utilisent tous les avantages de la communication en direct.

Par exemple, imaginez que vous créez un chat: vous devez recevoir et envoyer des données le plus rapidement possible, non? Les sockets Web font très bien avec cela! Vous pouvez ouvrir une connexion TCP et la maintenir ouverte aussi longtemps que nécessaire.

Les sockets Web sont apparues en 2010 dans Google Chrome 4, le premier RFC ( 6455 ) a été publié en 2011.

Les sockets Web sont utilisées dans les cas suivants:

  • Chats
  • Jeux multijoueurs
  • Montage collaboratif
  • Flux sociaux (actualités)
  • Applications basées sur la localisation

etc.

Socket.io


Socket.IO est une bibliothèque JavaScript basée (écrite en haut) sur les sockets web ... et d'autres technologies. Il utilise des sockets Web lorsqu'ils sont disponibles, ou des technologies telles que Flash Socket, AJAX Long Polling, AJAX Multipart Stream, lorsque les sockets Web ne sont pas disponibles. Une analogie facile est la comparaison de l'API Fetch et d'Axios.

Différence entre les sockets Web et Socket.IO


Les principaux avantages de Socket.IO sont les suivants:

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

Il peut sembler que Socket.IO est le meilleur outil de communication en direct. Cependant, il existe plusieurs situations où il est préférable d'utiliser des sockets Web.

Premièrement, les sockets Web sont pris en charge par tous les navigateurs modernes. Par conséquent, vous avez rarement besoin du support d'autres technologies fournies par Socket.IO.

Si nous parlons de trafic réseau, les sockets Web n'envoient que deux requêtes:

  • OBTENIR pour obtenir la page HTML
  • MISE À NIVEAU pour la connexion aux sockets Web

Cela vous permet de vous connecter au serveur. Et Socket.IO?

  • OBTENIR pour obtenir la page HTML
  • Bibliothèque cliente Socket.IO ( 207kb )
  • Trois longues requêtes Ajax d'interrogation
  • MISE À NIVEAU pour la connexion aux sockets Web

Dans le monde de JS, 207kb c'est beaucoup. Quelle utilisation irrationnelle du trafic réseau!

Dans npm, il existe un package «websocket-vs-socket.io» qui vous permet de comparer le trafic réseau de ces technologies:

Trafic réseau de socket Web:




Trafic réseau Socket.IO:




La différence est évidente!

Écrire un code


Serveur de socket Web simple


Dans notre programme sur Node.js, nous allons créer un serveur fonctionnant sur le port 3001. Chaque fois que le client se connecte, nous lui attribuons un ID unique. Lors de l'envoi d'un message au client, nous lui notifierons le succès: [<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}`)
  })
})

Bien! Mais que se passe-t-il si nous voulons envoyer un message à chaque client connecté? Les sockets Web ne prennent pas en charge le publipostage par défaut. Cela peut être implémenté comme suit:

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))
})

Simplement et facilement! Comme vous pouvez le voir, WebSocket.Server conserve les enregistrements de chaque client connecté, afin que nous puissions itérer et envoyer un message à tout le monde. Vous pouvez tester le code sur un ordinateur (MacOS) ou dans un navigateur (Chrome) .

Serveur simple sur Socket.IO


Ce n'était pas difficile. Socket.IO peut-il rendre cela encore plus facile? Comment écrire le même serveur sur 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}`)
  })
})

Le code est presque la moitié plus court! Comme vous pouvez le voir, la méthode de diffusion n'envoie pas de notification à l'expéditeur, nous sommes donc obligés de le faire manuellement.

Il y a un problème: le code ne peut pas être testé sur un client de socket Web standard. Cela est dû au fait que, comme indiqué précédemment, Socket.IO n'utilise pas de sockets Web purs, mais de nombreuses technologies pour prendre en charge tous les clients possibles. Alors, comment testons-nous ses performances?

// 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>

Vous devez utiliser un client spécial. Dans l'exemple ci-dessus, nous le chargeons à partir du CDN. Ce client nous permet d'effectuer des tests rapides (sales) dans le navigateur.

Comme vous pouvez le voir, nos exemples ne sont pas très différents. Cependant, si nous parlons de compatibilité, il faut se rappeler que Socket.IO fonctionne avec sa propre bibliothèque et ne peut pas être utilisé à des fins non liées au développement Web. Dans le même temps, les sockets Web peuvent être utilisées pour résoudre un large éventail de tâches, telles que la communication P2P, l'échange de données en temps réel entre les serveurs, etc.

Sur une note


Mise à l'échelle horizontale. Supposons que votre discussion ait gagné en popularité et que vous devez ajouter un autre serveur et un équilibreur de charge pour traiter les demandes. Eh bien, si vous ouvrez la connexion au "serveur 1", puis l'équilibreur vous fait passer au "serveur 2", vous obtiendrez l'erreur: "Erreur lors de la prise de contact WebSocket: code de réponse inattendu: 400". Socket.IO résout ce problème en utilisant des cookies (ou en routant des connexions basées sur les adresses sources), et les sockets Web n'ont pas un tel mécanisme.
Performance. Comme indiqué précédemment, Socket.IO fournit plusieurs couches abstraites au-dessus de la couche de transport des sockets Web. De plus, le compactage des données au format JSON est utilisé ici, il n'y a donc aucune possibilité d'envoyer des données binaires au serveur (et vice versa). Si vous avez besoin d'une telle fonctionnalité, vous devez «conjurer» le code de la bibliothèque afin d'assurer le comportement souhaité. Avec les sockets Web, de tels problèmes ne se posent pas.

Alors que choisir?


Tu décides.

Socket.IO vous facilite la vie, vous n'avez pas à vous soucier des problèmes liés à l'équilibrage de charge, à la déconnexion ou à l'envoi de messages ... mais avez-vous besoin d'une telle fonctionnalité? La bibliothèque cliente Socket.IO pèse plus que les packages React, Redux et React-Redux combinés. Êtes-vous sûr de ne pas pouvoir vous limiter aux sockets Web?

Une autre chose importante à garder à l'esprit est que lorsque vous utilisez Socket.IO côté serveur, la plupart du code sera écrit sur les abstractions fournies par cette bibliothèque. Si vous devez réécrire les microservices Node.js dans Go, Elixir, Java ou un autre langage de programmation, vous devrez réécrire presque toute la logique. Par exemple, pour envoyer des messages à Socket.IO, la méthode «broadcast» est utilisée (qui est implémentée manuellement sur les sockets Web), donc lors de la refactorisation, vous devrez comprendre comment cette méthode fonctionne. Les sockets Web doivent être privilégiées dans ce cas, car elles sont plus faciles à adapter.

Merci de votre attention.

All Articles