
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.
Изображения материала были созданы с помощью нейросети. Все права защищены ©