Простой WebSocket сервер на Node.js
Published: 2021-03-09 20:26:33

Сейчас мы с вами напишем простой WebSocket-сервер на node.js. При подключении к этому серверу в ответ придёт приветственное сообщение. А так же будет доступна к выполнению пара не сложных команд.

Для этого потребуется установить Node.js с менеджером пакетов npm, он идёт в комплекте

Настройка проекта
В начале, нам потребуется создать директорию будущего проекта

```bash
mkdir websocket-server-node
```
Переходим в директорию

```bach
cd websocket-server-node
```
Далее нужно инициализировать новый проект через npm

```bash
npm init
```
Установщик потребует ответить на несколько вопросов, их можно пропустить

После инициализации проекта, необходимо добавить в проект библиотеку WS и настройку для работы с текстом в UTF-8

```bash
npm install ws
npm install --save-optional utf-8-validate
```

##Код websocket-сервера
Теперь приступим к написанию кода. В директории проекта создадим новый файл server.js, откроем файл. Далее я последовательно опишу весь код, а вот [ссылка на полный код на GitHub](https://github.com/bkwebeagle/websocket-server-nodejs).

###server.js:
В начале нужно подключить библиотеку для работы с websocket

```javascript
const WebSocket = require('ws');
```
Далее, создадим константу, экземпляр класса WebSocket, с указанием порта на котором будет запущен WebSocket-сервер.

```javascript
const wsServer = new WebSocket.Server({port: 9000});
```
В отличии от HTTP-сервера, WebSocket-сервер принимает подключение и удерживает его. HTTP-сервер принимает запросы напрямую, а WebSocket-сервер принимает запросы от подключения, такое соединение является полнодуплексное.

Напишем обработчик подключения, в качестве обработчика укажем функцию onConnect.

```javascript
wsServer.on('connection', onConnect);
```
В момент подключения нового клиента в onConnection передаётся объекта ws-соединения, через него сервер будет общаться с каждым конкретным клиентом.

Функция onConnect принимает только один параметр, назовём его wsClient. В нашем конкретном примере мы подключим только два обработчика событий на объект wsClient: message и close.

*message* - обрабатывает событие входящего сообщения от клиента.

*close* - событие разрыва соединения с клиентом.

В самом начале функции onConnect, выведем в консоль сообщение что новый пользователь в сети. И отправим клиенту приветственное сообщение

Далее опишу заготовку для функции onConnect:
```javascript
function onConnect(wsClient) {
  console.log('Новый пользователь');
  // отправка приветственного сообщения клиенту
  wsClient.send('Привет');
  
  wsClient.on('message', function(message) {
    /* обработчик сообщений от клиента */
  }
  
  wsClient.on('close', function() {
    // отправка уведомления в консоль
    console.log('Пользователь отключился');
  }
}
```
На событие *close* сервер выведет в консоль уведомление.

Теперь напишем обработчик сообщений со стороны клиента. Договоримся, что команды сервер будет принимать в JSON-формате. JSON позволит отдельно указывать команду и параметры, а ответ сервера будет возвращаться в текстовом формате.

Формат JSON команд от клиента:
```json
{
  action: 'ECHO' | 'PING',
  data?: string // необязательный параметр
}
```
Как видно из формата, сервер будет принимать две команды:

echo-запрос, в ответ на который сервер отправит содержимое data
ping, в ответ сервер отправит pong
если команда не известна, сервер выведет в консоль уведомление "Неизвестная команда"
Содержимое обработчика сообщений от клиента:
```javascript
try {
  // сообщение пришло текстом, нужно конвертировать в JSON-формат
  const jsonMessage = JSON.parse(message);
  switch (jsonMessage) {
    case 'ECHO':
      wsClient.send(jsonMessage.data);
      break;
    case: 'PING':
      setTimeout(function() {
        wsClient.send('PONG');
      }, 2000);
      break;
    default:
      console.log('Неизвестная команда');
      break;
  }
} catch (error) {
  console.log('Ошибка', error);
}
```
Как вы уже видите, на команду PING сервер не сразу ответит, а подождёт 2 секунды.

Добавим в конце файла server.js строку, которая выведет в консоль информацию, на каком порту запущен сервер.
```javascript
console.log('Сервер запущен на 9000 порту');
```
Запуск сервера
Для запуска сервера необходимо перейти в консоль и ввести команду:

node server.js
Сервер доступен локально по адресу ws://localhost:9000. Остановить сервер можно сочетанием клавиш:

Для Windows и Linux (Ctrl + C)
Для MacOs (Cmd + C)
Если хотите проверить работу сервера с другого устройства в рамках локальной сети, то откройте ещё одно окно консоли и запустите команду 

для Window:
```bash
ipconfig
```
для Linux и MacOS:
```bash
ifconfig
```
В моём случае локальный адрес 192.168.0.15, значит из локальной сети сервер будет доступен по адресу ws://192.168.0.15:9000.

Проверка работы сервера
Чтобы протестировать работу сервера, откроем любую страницу в браузере и нажмём клавишу F12. Откроется DevTools, перейдём в консоль браузера и скопируем следующий код:
```javascript
const myWs = new WebSocket('ws://localhost:9000');

// обработчик проинформирует в консоль когда соединение установится
myWs.onopen = function () {
  console.log('подключился');
};

// обработчик сообщений от сервера
myWs.onmessage = function (message) {
  console.log('Message: %s', message.data);
};

// функция для отправки echo-сообщений на сервер
function wsSendEcho(value) {
  myWs.send(JSON.stringify({action: 'ECHO', data: value.toString()}));
}

// функция для отправки команды ping на сервер
function wsSendPing() {
  myWs.send(JSON.stringify({action: 'PING'}));
}
```
Запустите этот код. Далее в консоли браузера вызовите функцию wsSendPing:
```javascript
wsSendPing()
```
Через 2 секунды сервер пришлёт ответ, и в консоли выведется:

Message: PONG

Вызовите функцию wsSendEcho, к примеру, с содержимым "Test!", и в консоли будет выведено:

Message: Test!

Вот и всё! Кому понравилось, ставьте Like, подписывайтесь. Всем Добра!

[Ссылка на полный код GitHub](https://github.com/bkwebeagle/websocket-server-nodejs)