Что такое веб-сокет? Создаете приложение для чата в реальном времени, используя Socket.IO с NodeJS? Насколько легко это может быть? Мы увидим!

WebSocket обеспечивает двустороннюю связь в реальном времени между двумя или более клиентами через подключающийся сервер. Это противоречит WebRTC, который обеспечивает прямую двустороннюю связь в реальном времени между двумя или более клиентами без необходимости в постоянном наличии сервера [это означает, что после того, как сервер соединит клиентов, клиенты теперь могут общаться непосредственно друг с другом]. В следующий раз планирую писать на WebRTC 😃

Понимание преимуществ WebSocket может быть лучше реализовано при разработке приложения для чата. Прежде всего, отправка HTTP-запросов по сети для облегчения активной связи между клиентами была бы очень дорогостоящей. Избыточная информация заголовка должна будет передаваться по сети каждый раз. В то время как в случае соединений WebSocket, как только дорогостоящий первоначальный вызов устанавливает соединение между любыми двумя клиентами, теперь между собой можно отправлять очень небольшие пакеты данных. Это может способствовать более быстрой и легкой передаче данных, а также непрерывной передаче данных или потоков данных для аудио/видео и т. д. типов информации.

ОСТОРОЖНО, ЛЮДИ! в этой статье показаны фрагменты кода со смесью Javascript ES5 и ES6 😛

Как создать базовое приложение WebSocket в NodeJS?
* Серверное приложение для установления связи между клиентами. [NodeJS, NodeExpress, Socket.IO и т. д.]
* Клиентское приложение для прослушивания и отправки сообщений своей аудитории. [JS, HTML, CSS и т. д.]

Рекомендуется:
* Nodemon (для горячей загрузки, только для среды разработки, установите, если он еще не установлен глобально на вашем компьютере)

баш

npm i express
npm i socket.io
npm i -D nodemon //as dev dependency, use -g if desired

Скелет серверного приложения:

сервер.js

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var PORT = process.env.PORT || 5000;
//WE WILL USE THIS SERVER APP TO SERVE THE CLIENT ALSO!!
app.get('/', (req, res) => {
   res.sendFile(__dirname + '/index.html');
});
// ALL WEBSOCKET CODE GOES HERE...
http.listen(PORT, function () {
   console.log('WebSocket App started on PORT: ' + PORT);
});

Как видите, здесь мы загрузили нашу библиотеку Socket IO. Давайте используем его для прослушивания любого клиента, который хочет подключиться к нашему приложению на хосте и заданном порту. Любой клиент, который откроет соединение WebSocket, используя наш хост и порт, неявно инициирует событие соединения «соединение» и будет подключен.

сервер.js

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var PORT = process.env.PORT || 5000;
// Listening to clients getting connected and disconnected
io.sockets.on('connection', function(socket) {
    console.log("LOG: [EVENT=connection] New client connected.");
//A client left
    socket.on('disconnect', function() {
        console.log("LOG: [EVENT=disconnect] client has disconnected.");
    });
});
http.listen(PORT, function() {
    console.log('WebSocket App started on PORT: ' + PORT);
});

Клиентская сторона:
index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>terminal-x</title>
  </head>
  <body>
    <!-- ALL HTML GOES HERE -->
    <textarea id="outputID" row="0" readonly></textarea>
    <input id="inputID" type="text" />
    <!-- SCRIPT GOES HERE -->
    <script src="/socket.io/socket.io.js"></script>
    <script src="/client.js"></script>
  </body>
</html>

client.js:

//SOCKET CONNECTION CHATROOM
      var sock = io.connect();
      //THIS IS WHERE WE WILL EVENTUALLY ADD CODES
      //TO EMIT AND LISTEN FOR MESSAGES FOR EACH EVENT

🌹КОМНАТЫ!
Для обеспечения конфиденциальности и облегчения групповых чатов мы будем использовать комнаты. Комнаты — это отдельные каналы, созданные внутри одного и того же сокетного соединения. Несколько клиентов могут присоединиться к каждому каналу/комнате и вести отдельные групповые беседы.

🍓 Приведенный ниже пример кода в значительной степени завершает работу над серверным приложением:
Как видите, первое событие, которое мы хотим прослушать, — это событие «соединение», когда клиенты подключаются к нашему веб-сокету, теперь мы слушаем для события 'join_room'. Каждый раз, когда клиент хочет создать комнату с новым именем, мы создаем для этого комнату/канал. Если клиент хочет создать канал/комнату с существующим именем, он просто игнорируется. Дублирование теперь разрешено. Может быть реализован механизм добавления уникального идентификатора каждый раз, когда клиенты пытаются открыть комнаты/каналы с тем же именем.

client.js

room_name = "room name I want to create and subscribe";
sock.emit('join_room', room_name);

сервер.js

// server side code: ROOM
io.sockets.on('connection', function(socket) {
    socket.on('join_room', function(room_name) {
        socket.join(room_name);
        console.log(socket.rooms); //all rooms created so far
    });
});

Прослушивание комнат. Со стороны сервера мы прослушиваем событие «message_to_server», это событие может быть запущено на стороне клиента из любой комнаты. Затем мы передадим это сообщение каждому клиенту в этой комнате. Теперь, как мы узнаем, из какой комнаты он пришел? Мы добавим это имя комнаты в данные самим клиентом. Как вы можете видеть в коде ниже

сервер.js

//LISTEN TO ROOMS
socket.on('message_to_server', function({
    room_name,
    from,
    msg
}) {
    //we will emit this message to all clients in given room
});

Передача в комнаты: мы получили это со стороны клиента, сообщая пользователю, что это за комната, кто пользователь и что это за сообщение. Теперь мы можем отправить это сообщение

сервер.js

//LISTEN TO ROOMS AND EMITTING TO ALL CLIENTS IN THAT ROOM
socket.on('message_to_server', function({
    room_name,
    from,
    msg
}) {
    //we will emit this message to all clients in given room
    io.in(room_name).emit('message_to_client', {
        from,
        msg
    });
});

client.js

// EMITTING MESSAGES FROM CLIENT TO ROOM
var room_name = "name of room to which we will emit"
var from = "could be username, some way to identifiy who sent it"
var msg = "the message from this client"
sock.emit('message_to_server', { room_name, from: username, msg });

Приведенный выше код будет запущен пользователем из пользовательского интерфейса клиента, используя событие 'message_to_server', мы добавляем имя пользователя и имя комнаты в полезную нагрузку, поэтому серверная сторона может знать, в какой комнате это сообщение. должны быть отправлены в.

Вот, полный код с комментариями! давайте изучим не требующий пояснений полный пример кода.

сервер.js

"use strict";
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var PORT = process.env.PORT || 5000;
app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});
// server side code: ROOM
io.sockets.on('connection', function(socket) {
    console.log("LOG: [EVENT=connection] New client connected.");
//EACH TIME WE WANT TO CREATE A NEW ROOM FROM CLEINT SIDE, EVENT = CREATE
    socket.on('join_room', function(room_name) {
        console.log("LOG: [EVENT=join_room] [room_name=" + room_name + "]");
        console.log(socket.rooms);
        socket.join(room_name);
    });
//LISTEN TO ROOMS
    socket.on('message_to_server', function({
        room_name,
        from,
        msg
    }) {
//we will emit this message to all clients in given room
io.in(room_name).emit('message_to_client', {
            from,
            msg
        });
    });
//A user disconnected from room
    socket.on('disconnect', function() {
        console.log("LOG: [EVENT=disconnect] A client has disconnected.");
    });
});
http.listen(PORT, function() {
    console.log('WebSocket App started on PORT: ' + PORT);
});

Давайте посмотрим на клиентский скрипт. Большая часть кода статична для простоты понимания. После базового понимания его можно сделать динамическим и запускаемым по событию.

client.js

//SOCKET CONNECTION CHATROOM
   var sock = io.connect();
   var outputDOM = document.getElementById("outputID");
   var inputDOM = document.getElementById("inputID");
   var username = "";
   var msg = "";
   var room_name = "";
   //+++++++++++++++++++++++++++++++++++++
   // REQUEST SERVER TO CREATE A NEW ROOM:
   //+++++++++++++++++++++++++++++++++++++
   room_name = "some room name";
   sock.emit('join_room', room_name);
   //+++++++++++++++++++++++++++++++++++++
   // LISTENER TO SERVER:
   //+++++++++++++++++++++++++++++++++++++
   sock.on('message_to_client', function({
       from,
       msg
   }) {
       // ******
       outputDOM.innerHTML += "</br>" + decryptedMSG(data);
       outputDOM.rows += 1;
       // ******
   });
   //+++++++++++++++++++++++++++++++++++++
   // SEND TO SERVER:
   //+++++++++++++++++++++++++++++++++++++
   function sendToServer(msg, room_name) {
       sock.emit('message_to_server', {
           room_name,
           from: username,
           msg
       });
   }
   //USER GAVE INPUT: SEND TO SERVER
   inputDOM.addEventListener("keyup", function(event) {
       if (event.keyCode === 13) {
           event.preventDefault();
           //+++++++++++++++++++++++++++++++++++++
           if (inputDOM.value != "") {
               //SEND TO SERVER
               sendToServer(inputDOM.value, token);
               //RESET INPUT TERMINAL
               inputDOM.value = ""
           } else {
               inputDOM.placeholder = "empty message cant be sent!";
           }
           //+++++++++++++++++++++++++++++++++++++
       }
   });

Если все еще есть путаница, взгляните на полный проект на WebSocket с использованием комнат. Клонируйте его и следуйте инструкциям в readme.md. Это не базовый шаблон для приложения Socket, но он должен быть достаточно простым для понимания.
ССЫЛКА: полный пример проекта, написанный с помощью Socket.IO в nodeJS.



Данный проект можно легко развернуть в Heroku. Добавлены два сценария оболочки. Наслаждаться!! пожалуйста, оставьте комментарии или аплодисменты!!