Программирование сокетов. Сеть и сокет
Web Sockets (веб-сокеты) — это технология, позволяющая создавать интерактивное соединение для обмена сообщения в онлайн-режиме.
Как функционирует HTTP?
Про протокол HTTP (HTTPS) знает каждый, так как мы постоянно встречаемся с ним в своих браузерах. Как правило, браузер постоянно запрашивает у сервера, есть ли для него сообщения, а потом получает их. Здесь возможны различные типы запросов (POST, GET, PUT), причём каждый из них имеет своё назначение. Особенности работы хорошо видны на картинке:
А что сокеты?
Сокет для ответа не нуждается в ваших повторяющихся запросах. Сокет в сети работает таким образом, что достаточно лишь один раз выполнить запрос, а потом ждать отклика. И вы можете спокойно «слушать» сервер, который отправит сообщения по мере готовности.
Когда используют веб-сокет?
Сокет применяется в том случае, если вы, к примеру, разрабатываете: — чат- и IoT-приложения; — программы, работающие в режиме реального времени; — многопользовательские игры.
Когда нежелательно применять сокет?
Особых противопоказаний в отношении сокета и сокетов нет. Один из недостатков — несовместимость с некоторыми видами браузеров, но этот минус уже практически изжил себя, так как сегодня около 95 % браузеров поддерживают сокеты.
Тем не менее иногда сокет вам всё же не нужен, и зависит это от того, с каким типом приложения вы будете работать. Например, вы создаёте простую CMS и вам совершенно нет нужды обеспечивать функциональность в режиме реального времени.
Не стоит применять сокет и в REST API, так как будет вполне достаточно стандартных HTTP-запросов (GET, DELETE, POST и PUT). В целом специалисты не рекомендует использовать сокет, если это не риалтайм-приложение, но вопрос о недостатках сокетов требует более детального рассмотрения в рамках отдельной статьи.
От теории к практике
Давайте напишем сокет самостоятельно. Для создания клиента будем использовать язык программирования JavaScript, а для создания сервера — Node.js.
Собственно говоря, мы подобрали максимально простые примеры, которые в первую очередь нужны для того, чтобы разобраться в сути такой технологии, как сокет.
Cоздание клиента
<!DOCTYPE html> <html> <head> <title>Пример чата с сокетом</title> </head> <body> <script> let ws = new WebSocket("ws://localhost:8080"); // выведем новые сообщения в нашу консоль ws.onmessage = ({data}) => { console.log(data); } // отправим сообщение ws.onopen = () => ws.send('Text'); </script> </body> </html>
Cоздание сервера
const WebSocket = require('ws'); // создаём новый сокет-сервер const wss = new WebSocket.Server({ port: 8080 }); // отправляем клиентам, если функция `clientValidator` возвращает true. This — это wss. wss.broadcast = function(data, clientValidator = () => true) { this.clients.forEach(client => { if (clientValidator(client)) { client.send(data); } }); } wss.on("connection", ws => { // событие вызовется, если клиент отправит сообщение ws.on('message', message => { // отправим сообщение всем за исключением автора wss.broadcast(message, client => client !== ws); }); });
И что в итоге?
Что же, давайте продемонстрируем работу созданных нами сокетов:
Есть ли эквивалент сокету в HTTP?
В принципе, есть. Смотрите, HTTP должен проверять канал в сети на наличие новых сообщений. Следовательно, мы можем задействовать dirty check, то есть «грязную проверку». При этом подходе клиент с заданной периодичностью (например, каждые 100 мс) будет проверять, есть ли новые сообщения на сервере. Не вникая в XMLHttpRequest, можно применять библиотеку Axios. Это достаточно понятный и декларативный инструмент. Итак, наш клиент:
<!DOCTYPE html> <html> <head> <title>Обмениваемся сообщениями в режиме онлайн</title> </head> <body> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <script> let localMessages = []; // первоначальное обновление локального сообщения axios.get('http://localhost:8080/messages') .then(({data}) => localMessages = data.messages); // обновление списка сообщений const updateMessages = () => { axios.get('http://localhost:8080/messages') .then(({data}) => { const difference = data.messages.splice(localMessages.length); difference.forEach(message => { console.log(message); localMessages.push(message); }); }) .catch(console.log); } // отправка сообщения const sendMessage = text => { axios.post('http://localhost:8080/messages', {text}); } // каждые 100 мс проверяем, присутствуют ли новые сообщения setInterval(updateMessages, 100); </script> </body> </html>
А теперь посмотрим, что делается на сервере:
const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json(), function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); }); // в реальном приложении сообщения сохранялись бы в БД либо в JSON-файлах // но не в переменной, которая, как известно, обнуляется в случае остановки сервера let messages = []; // создается новое сообщение app.post('/messages', (req, res) => { messages.push(req.body.text); res.json({ success: true }); }); // получаем все сообщения app.get('/messages', (req, res) => { res.json({ messages }); }); // «слушаем» все запросы на localhost: 8080. app.listen(8080, () => console.log('Слушаю порт 8080'));
Делаем выводы
Можно с уверенностью заявить, что сокет — довольно перспективная веб-технология, поэтому уже сейчас её использует множество разработчиков. Кроме того, сокеты прекрасно подходят для взаимодействия в реальном времени, включая онлайн-игры.
Источники: • https://medium.com/@td0m/what-are-web-sockets-what-about-rest-apis-b9c15fd72aac; • https://tproger.ru/translations/what-are-web-sockets/.