Как сделать сервер WebSocket с помощью JavaScript: мне нравятся мои серверы, как мне нравится мой кофе, мой собственный

Как сделать сервер WebSocket с помощью JavaScript: мне нравятся мои серверы, как мне нравится мой кофе, мой собственный

10 апреля 2022 г.

Большая часть работы, которую мы выполняем с помощью Javascript, связана с отправкой информации с серверов туда и обратно.


Вы, вероятно, знакомы с концепцией API, которые отправляют данные на серверы или веб-сайты в определенном формате, чтобы получить определенный ответ.


Они известны как REST API. Хотя они полезны, они не очень хороши в постоянных потоках данных.


Если вы попытаетесь сделать что-то в реальном времени с помощью REST API, у вас будут плохие времена. К счастью, если нам нужно соединение с пользователем в режиме реального времени, у нас есть альтернатива, известная как WebSockets.


Как работают веб-сокеты


В этом руководстве мы предполагаем, что вы знакомы с Node.JS.


WebSockets — это, по сути, постоянные соединения между сервером и вашим компьютером.


Когда вы заходите на веб-сайт, он может отправить запрос GET на сервер, чтобы инициировать соединение WebSocket между пользователем и сервером.


Веб-сокет против. ОТДЕЛЬНЫЙ API


Как работает WebSocket


Если пользователь покидает веб-сайт, соединение прерывается, поэтому пользователь имеет доступ к WebSocket только до тех пор, пока он продолжает использовать веб-сайт.


Как долго WebSocket может оставаться открытым?


После создания WebSocket теоретически он может оставаться открытым вечно. Есть несколько исключений из этого:


  • Сервер выходит из строя — это сломает WebSocket, но мы можем попытаться переподключиться к нему.

  • Отключение электроэнергии или проблема с интернет-соединением - соединение прервется, если у пользователя прекратится интернет.

  • Неактивность — если пользователь не взаимодействует и не отправляет данные через WebSocket, время ожидания соединения неизбежно истекает.

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


Создание WebSocket


Таким образом, WebSocket состоит из двух частей: сервера и локальной машины, которую использует пользователь. Для того, что мы делаем, мы будем использовать Node.JS в качестве нашего сервера, но другие языки также поддерживают WebSockets.


Когда пользователь обращается к нашему веб-сайту, мы загружаем файл с некоторым Javascript, который содержит строку подключения к нашему WebSocket.


Между тем, в нашем бэкэнде у нас будет настроен WebSocket, к которому будет подключаться пользователь. Это показано на диаграмме ниже:


Как работает WebSocket


Шаг 1: Создание нашего сервера


Давайте начнем с создания нашего веб-сервера Node.JS для подключения WebSocket. Для этого мы будем использовать экспресс-сервер с дополнительным пакетом под названием express-ws. Этот дополнительный пакет позволит нам использовать ws так же, как мы могли бы использовать get с экспрессом.


Если у вас не установлен Node.JS, вам необходимо сначала сделать это [перейдя по этой ссылке] (https://nodejs.org/en/download/). После установки создайте новую папку с именем server-websocket.


Откройте терминал и используйте cd для перехода в эту папку (если вы не знаете о cd, прочитайте мою статью об этом здесь!).


Как создать каталог из командной строки


Создайте папку для вашего WebSocket


Оказавшись в папке, вам необходимо установить пакеты зависимостей. Начните установку своих зависимостей, выполнив каждую из следующих команд:


нпм я выражаю


npm я экспресс-WS


нпм я путь


нпм я URL


После этого создайте файл index.js и вставьте в него следующий код:


```javascript


// Импорт зависимостей пути и URL


импортировать путь из пути


импортировать {fileURLToPath} из 'url'


// Получаем каталог и путь к файлу


const __filename = fileURLToPath(import.meta.url);


const __dirname = path.dirname(__filename);


// Импорт экспресс, expressWs и http


импортировать экспресс из «экспресс»


импортировать expressWs из 'express-ws'


импортировать http из 'http'


// Наш порт


пусть порт = 3000;


// Приложение и сервер


пусть приложение = экспресс();


пусть сервер = http.createServer(приложение).listen(порт);


// Применение экспресс-запросов


expressWs (приложение, сервер);


app.use(express.static(__dirname + '/views'));


// Получить маршрут /


app.get('/', (требование, разрешение) => {


res.status(200).send("Добро пожаловать в наше приложение");


// Это позволяет серверу выбрать маршрут WebSocket '/ws'


app.ws('/ws', асинхронная функция(ws, req) {


// После чего ждем сообщения и отвечаем на него


ws.on('сообщение', асинхронная функция (msg) {


// Если появится сообщение, мы запишем его в консоль на сервере


console.log(сообщение);


// начинаем слушать сообщения


Последнее предложение, app.ws, относится к WebSocket, и это то, к чему мы попытаемся подключиться во внешнем интерфейсе.


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


```javascript


// Получить маршрут веб-сокета /ws


app.ws('/ws', асинхронная функция(ws, req) {


ws.on('сообщение', асинхронная функция (msg) {


// Что было в сообщении?


console.log(сообщение);


// Отправляем обратно некоторые данные


ws.send(JSON.stringify({


"добавить": правда,


"returnText": "Я использую WebSockets!"


Теперь всякий раз, когда это соединение WebSocket получает данные, оно будет отправлять обратно объект, содержащий append и returnText. Мы также запишем в консоль сообщение, полученное сервером.


Затем мы можем манипулировать этим объектом в нашем интерфейсе, чтобы отображать или изменять представления для пользователя.


Сохраните этот файл в папке вашего веб-сервера как index.js. Затем с вашего терминала в папке websocket-server выполните следующую команду:


узел index.js


Шаг 2. Подключение через внешний интерфейс


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


  • Пользователь посещает наш сайт.

  • Мы инициируем соединение WebSocket из нашего файла Javascript.

  • Пользователь успешно подключается к WebSocket и отправляет сообщение в WebSocket после подключения.

  • Затем мы можем отправить данные обратно пользователю, теперь, когда у него есть живое соединение с нашим сервером WebSocket, создавая обмен данными в реальном времени.

Для нашей демонстрации давайте начнем с создания двух файлов: index.html и local.js, оба из которых будут файлами внешнего интерфейса. Далее добавим в наш файл index.html следующее:


```html


<скрипт src="local.js">


Добро пожаловать в WebSockets. Нажмите здесь, чтобы начать получать сообщения.




Далее нам нужно подключить пользователя к нашему WebSocket через файл local.js. Наш файл local.js в конечном итоге будет выглядеть так:


```javascript


// @соединять


// Подключаемся к вебсокету


пусть розетка;


// Это позволит нам создать соединение с веб-сокетом нашего сервера.


// Чтобы это работало, ваш веб-сокет должен работать с узлом index.js


константное соединение = функция () {


// Возвращаем промис, который будет ждать открытия сокета


вернуть новое обещание ((разрешить, отклонить) => {


// Это вычисляет ссылку на веб-сокет.


const socketProtocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:')


постоянный порт = 3000;


const socketUrl = ${socketProtocol}//${window.location.hostname}:${port}/ws/


// Определяем сокет


// Если вы используете свой веб-сокет на локальном хосте, вы можете изменить


// socketUrl на 'http://localhost:3000', так как мы запускаем наш веб-сокет


// на порту 3000 из предыдущего кода веб-сокета.


сокет = новый WebSocket (socketUrl);


// Это сработает, как только сокет откроется


socket.onopen = (е) => {


// Отправляем немного тестовых данных, которые мы можем использовать на сервере, если захотим


socket.send (JSON.stringify ({ "загружено": правда }));


// Решаем промис - мы подключены


разрешить();


// Это срабатывает, когда сервер отправляет пользователю сообщение


socket.onmessage = (данные) => {


console.log(данные);


// Здесь можно манипулировать любыми данными с сервера.


пусть parsedData = JSON.parse(data.data);


если (parsedData.append === true) {


const newEl = document.createElement('p');


новыйEl.textContent = parsedData.returnText;


document.getElementById('websocket-returns').appendChild(newEl);


// Это сработает при ошибке


socket.onerror = (e) => {


// Возвращаем ошибку, если она возникла


console.log(е);


разрешить();


// Пытаемся снова подключиться


соединять();


// @открыт


// проверяем, открыт ли вебсокет


константа isOpen = функция (ws) {


вернуть ws.readyState === ws.OPEN


// Когда документ загрузился


document.addEventListener('DOMContentLoaded', function() {


// Подключаемся к вебсокету


соединять();


// И добавляем наши прослушиватели событий


document.getElementById('websocket-button').addEventListener('щелчок', function(e) {


если (открыто (гнездо)) {


socket.send(JSON.stringify({


"data": "это наши данные для отправки",


"другое": "это может быть в любом формате"


Может показаться, что это много, но давайте разберемся. В нашей функции подключения мы начинаем с создания нашего URL-адреса WebSocket.


Это можно просто записать как ws://localhost:3000/, так как наш сервер WebSocket работает на порту 3000. Выше он настроен на автоматическую настройку, если вы используете HTTP или HTTPS.


Затем мы передаем несколько прослушивателей событий нашему вновь созданному WebSocket. Все наши прослушиватели событий и URL-адрес для подключения к серверу WebSocket находятся в нашей функции connect(), целью которой является подключение к нашему серверу WebSocket.


Наши прослушиватели событий WebSocket выглядят так:


  • socket.onopen - если соединение установлено и открыто, срабатывает.

  • socket.onmessage — каждый раз, когда сервер отправляет нам сообщение, это срабатывает. В нашем примере мы добавим новый элемент в HTML-код нашего пользователя, если они получат данные, для которых добавление установлено в true.

  • socket.onerror - если соединение не установлено или возникает ошибка, это сработает.

Теперь, когда у нас есть функция connect(), которая позволяет нам подключаться к нашему серверу WebSocket, мы должны запустить ее. Мы начинаем с ожидания загрузки страницы, используя DOMContentLoaded. Затем мы подключаемся к нашему WebSocket, используя функцию connect().


Наконец, мы прикрепляем прослушиватель событий к кнопке на нашей HTML-странице, которая при нажатии теперь будет отправлять некоторые данные в наш WebSocket с помощью функции socket.send().


Когда сервер получает эти данные, он затем отправляет обратно свои собственные данные, поскольку срабатывает событие «сообщение» сервера.


```javascript


// Когда документ загрузился


document.addEventListener('DOMContentLoaded', function() {


// Подключаемся к вебсокету


соединять();


// И добавляем наши прослушиватели событий


document.getElementById('websocket-button').addEventListener('щелчок', function(e) {


если (открыто (гнездо)) {


socket.send(JSON.stringify({


"data": "это наши данные для отправки",


"другое": "это может быть в любом формате"


Поскольку наш обработчик событий on message на нашем WebSocket срабатывает всякий раз, когда новые данные поступают с сервера WebSocket, нажатие кнопки заставляет сервер WebSocket отправлять нам сообщение, создавая таким образом новый элемент HTML

.


Вывод


Теперь у нас есть работающий WebSocket, который позволяет отправлять данные на сервер, и обратно пользователю.


Это двустороннее соединение можно использовать, чтобы позволить пользователям взаимодействовать с самим сервером и даже отправлять данные другим пользователям, если вы того пожелаете. Вот несколько полезных ссылок, чтобы узнать больше о WebSockets:


  • [Загрузить исходный код через Github.] (https://github.com/smpnjn/express-websocket)


  • [Больше руководств по Javascript] (https://fjolt.com/category/javascript)

Ранее опубликовано [здесь] (https://fjolt.com/article/javascript-websockets)



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE