HTTP, Server Sent Events (SSE), Websockets и Long Polling

Существуют разные способы коммуникации клиента с сервером. В этом материале предлагаю рассмотреть HTTP, Server Sent Events, Websockets и Long Polling.
HTTP
Протокол работает так: клиент открывает соединение, отправляет запрос на сервер, сервер шлет ответ и соединение закрывается. Таким образом можно обмениваться данными между клиентом и сервером (и между серверами).
HTTP был придуман Тимом Бернерс-Ли в 1989-1991 году. Первая версия 0.9 имела лишь метод GET, а запрос выглядел так:
GET /index.html
Тогда в запросе еще не было сервера и порта. А в ответ приходила HTML-разметка в чистом виде без каких-либо HTTP-заголовков. Соответственно, не было ни статус-кодов, ни возможности отправить json.
HTTP/1.0
В этой версии появились HTTP-заголовки, включая Content-Type, появились статусы как запроса так и ответа.
Запрос выглядел так:
GET /mypage.html HTTP/1.0 User-Agent: NCSA_Mosaic/2.0 (Windows 3.1) 200 OK Date: Tue, 15 Nov 1994 08:12:31 GMT Server: CERN/3.0 libwww/2.17 Content-Type: text/html <HTML> A page with an image <IMG SRC="/myimage.gif"> </HTML> </pre>
Первая версия все еще не была стандартизирована.
HTTP/1.1
- Появилась возможность не закрывать соединение при последовательных запросах на сервер.
- Стала возможной отправка второго запроса до того как получен ответ на первый.
- Поддержка chunked для файлов больших размеров
- Добавлен механизм кеширования, о котором я рассказывал ранее
- Появился host заголовок, который позволил использовать несколько доменов на одном сервере.
Благодаря своей гибкости, протокол постоянно расширялся, появлялись новые заголовки. Самым крупным изменением в 1994 году стало использование SSL - зашифрованного транспортного слоя поверх HTTP.
С годами в HTTP появились способы защиты пользователей веба. Так появились Content Security Policy и Cross Origin Resource Sharing (CORS). Первый заголовок защищает от CSRF и XSS атак, жестко ограничивая возможности по скачиванию ресурсов, будь то JS или CSS. CORS также защищает от межсайтовых атак (когда с домена злоумышленника делается запрос на другой домен, в котором пользователь авторизован).
HTTP/2.0
Современный веб сложный и ресурсоемкий. HTTP/1.1 имеет ограничение в 5-8 одновременных запросов, что делает его не очень быстрым при передаче большого числа файлов с сервера.
Протокол позволяет отправлять теоретически бесконечное количество запросов в одном соединении, таким образом, ничего не будет блокировать передачу файлов. HTTP/2.0 - бинарный протокол, со сжатием заголовков и механизмом Server Push для передачи ассетов страницы еще в момент загрузки страницы (он будет отключен в Chrome 106)
Long Polling
Это процесс, при котором соединение между сервером и клиентом не разрывается длительный период, а при разрыве повторно создается. Такой механизм позволяет передавать промежутками различные данные. Например, он неплох для отправки статусов бизнес-сущностей клиенту или любой другой real-time информации. В отличие от обычных запросов, здесь создается всего одно соединение, что уменьшает нагрузку на сервер и ускоряет передачу.
Работает Long Polling так:
- Клиент делает запрос
- Сервер принимает запрос и не отвечает до тех пор, пока ему не будет чем ответить.
- Клиент получает ответ и заново делает запрос.
Могут быть кейсы, когда сервер из-за слишком долгого ответа закрыл соединение, в этом случае запрос делается повторно.
Для реализации Long Polling необходимо, чтобы сервер держал соединение открытым до тех пор пока ему не будет чем ответить, поэтому реализовать Long Polling без взаимодействия с бэкендерами не получится.
Server Sent Events (SSE)
Это расширение к HTTP, с помощью которого можно с сервера отправлять запросы на клиент. Это отличная замена Long Polling. Идеально подойдет для динамически изменяемой информации в приложении. Например, различная real-time статистика, текстовые трансляции матчей и так далее. В этих случаях нет необходимости использовать WebSockets, так как клиент ничего не отправляет серверу.
Как попробовать? Необходимо на сервере в заголовках отправлять:
'Content-Type': 'text/event-stream',
На клиенте открываем соединение через EventSource и вешаем обработчик на eventSource 'message' событие:
const ev = new EventSource(''); ev.addEventListener('message', (e) => { console.log('data', e.data): })
.
WebSocket
Подойдет, если необходимо реализовать двунаправленную постоянную передачу данных, например, чаты, игры, торговые площадки.
Браузер сначала делает HTTP-запрос с заголовками Connection: Upgrade
и Upgrade: websocket
для смены протокола на websocket. Сервер в ответ отправляет код 101 и соединение переключается на websocket.
Данные передаются в виде "фреймов" (фрагментов). Вот так выглядит пример отправки сообщения:
Пример чата
let socket = new WebSocket("wss://javascript.info/article/websocket/chat/ws"); // отправка сообщения из формы document.forms.publish.onsubmit = function() { let outgoingMessage = this.message.value; socket.send(outgoingMessage); return false; }; // получение сообщения - отобразить данные в div#messages socket.onmessage = function(event) { let message = event.data; let messageElem = document.createElement('div'); messageElem.textContent = message; document.getElementById('messages').prepend(messageElem); }
На сервере необходимо хранить стейт клиентов и отправлять им сообщения при событии 'message':
const ws = new require('ws'); const wss = new ws.Server({noServer: true}); const clients = new Set(); http.createServer((req, res) => { wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onSocketConnect); }); function onSocketConnect(ws) { clients.add(ws); ws.on('message', function(message) { for(let client of clients) { client.send(message); } }); ws.on('close', function() { clients.delete(ws); }); }
Источник: learn.javascript
Поддерживается буфер для отложенной передачи данных на случай, если соединение пользователя нестабильно.
Обычно для работы с вебсокетами используют библиотеку socket.io.
Выводы:
Вот мы и разобрались кратко со способами коммуникации клиента с сервером. Что выбирать для вашего проекта? Зависит от кейсов. Для одних фич вам может понадобиться SSE, для других достаточно обычного HTTP 1.1.
Изображения материала были созданы с помощью нейросети. Все права защищены ©