Обычно, когда браузер посещает веб-страницу, HTTP-запрос отправляется на веб-сервер, на котором размещена эта страница. Веб-сервер подтверждает этот запрос и отправляет ответ.
Во многих случаях, например, для цен на акции, новостных отчетов, продаж билетов и т. Д., Ответ может быть устаревшим к тому моменту, когда браузер отображает страницу.
Если вы хотите получать самую актуальную информацию в режиме реального времени, вы можете постоянно обновлять эту страницу вручную, но это явно не лучшее решение.
Попытки
Примерно в 2005 году с помощью AJAX веб-браузер мог сказать серверу: «Привет, я хотел бы обновить этот раздел веб-страницы». Все немного ускорилось, но это все еще был веб-браузер, запрашивающий что-то с веб-сервера.
На основе AJAX было построено множество технологий, все они зависели от javascript без создания нового протокола с использованием HTTP (моделирование).
- Опрос
- Длинный опрос
- Потоковое / вечный ответ
- Множественные подключения
И каждый метод решает проблему, обнаруженную в предыдущем.
Опрос «продолжайте спрашивать»
- Браузер регулярно отправляет HTTP-запросы и сразу получает ответ.
- Сервер всегда немедленно отвечает с данными или без них.
НО…
- Это хорошее решение, если известен точный интервал доставки сообщения, потому что вы можете синхронизировать клиентский запрос, чтобы он происходил только тогда, когда информация доступна на сервере. Однако данные в реальном времени часто не так предсказуемы, что делает ненужные запросы неизбежными и, как следствие, многие соединения открываются и закрываются без нужды в ситуациях с низкой скоростью передачи сообщений.
- Очевидные потери (ЦП и пропускная способность) при отсутствии данных.
Пример
Web Browser: I'm going to keep this line open in case you have somestuff to send me. Web Server: Okay. Check on me. Web Browser: You got anything yet? Web Server: No. Web Browser: You got anything yet? Web Server: No Web Browser: You got anything yet? Web Server: Yep, here it is.
Длинный опрос
Чтобы решить проблему потери ЦП и полосы пропускания при опросе, браузер отправляет запрос на сервер, и сервер сохраняет запрос открытым в течение установленного периода. Если уведомление получено в течение этого периода, клиенту отправляется ответ, содержащий сообщение. Если уведомление не получено в течение установленного периода времени, сервер отправляет ответ, чтобы завершить открытый запрос.
- Браузер отправляет первоначальный запрос.
- Сервер ждет, пока у него не появятся данные для ответа.
- Браузер получает ответ и сразу создает новый запрос (цикл)
(function poll() { setTimeout(function () { $.ajax({ url: 'https://api.example.com/endpoint/', success: function (data) { //Do something with 'data' //.. //Setup the next poll recursivly poll(); }, datatype: 'json' }); }); })();
- Каждый запрос / ответ создает и закрывает соединение
- Когда у вас большой объем сообщений, длинный опрос не обеспечивает каких-либо существенных улучшений производительности по сравнению с традиционным опросом.
Потоковая передача
Решить проблему открытия / закрытия соединения при длительном опросе.
Браузер отправляет полный запрос, но сервер отправляет и поддерживает открытый ответ, который постоянно обновляется и остается открытым неопределенное время (или в течение определенного периода времени).
Затем ответ обновляется всякий раз, когда сообщение готово к отправке, но сервер никогда не сигнализирует о завершении ответа, тем самым сохраняя соединение открытым для доставки будущих сообщений.
Однако, поскольку потоковая передача по-прежнему инкапсулирована в HTTP, промежуточные межсетевые экраны и прокси-серверы могут выбрать буферизацию ответа, увеличивая задержку доставки сообщения.
Поэтому многие потоковые решения Comet возвращаются к длительному опросу в случае обнаружения буферизирующего прокси-сервера. В качестве альтернативы можно использовать соединения TLS (SSL) для защиты ответа от буферизации, но в этом случае установка и отключение каждого соединения более сильно нагружает доступные серверные ресурсы.
So…
- Клиент отправляет первоначальный запрос.
- Сервер ждет, пока у него не появятся данные для ответа.
- Сервер отвечает потоковыми данными.
- Связь поддерживается
Но…
- Есть проблемы с прокси.
- Полудуплекс (расскажу об этом)
Это были методы push на стороне сервера, и браузер не мог ничего отправить на сервер в соединении.
Несколько подключений
- Длительный опрос по двум отдельным HTTP-соединениям, одно для восходящего потока, например, текущих координат uber-клиента, и одно для нисходящего потока, например, для получения текущих координат uber-драйвера.
Но…
- Для каждого клиента используются два соединения.
- Нетривиальная координация и управление подключением
Скрытая стоимость упомянутого метода HTTP
- Рукопожатие TCB при установлении нового соединения (еще хуже в SSL).
- Заголовки HTTP в каждом сообщении.
«Уменьшение количества килобайт данных до 2 байтов… и уменьшение задержки со 150 мс до 50 мсек - это намного больше, чем предельное значение. Фактически, одних этих двух факторов достаточно, чтобы сделать WebSocket серьезно интересным для Google ».
- Ян Хиксон (Google, руководитель спецификации HTML5)
Режимы подключения
Односторонний
- Симплексный канал связи отправляет информацию только в одном направлении. Например, радиостанция обычно посылает сигналы аудитории, но никогда не принимает сигналы от них.
Полудуплекс
- В полудуплексном режиме данные могут передаваться на несущей сигнала в обоих направлениях, но не одновременно. В определенный момент это фактически симплексный канал, направление передачи которого можно переключать.
- Рация - это типичное полудуплексное устройство. Он имеет кнопку «нажми и говори», которую можно использовать для включения передатчика, но выключения приемника. Следовательно, как только вы нажмете кнопку, вы не сможете услышать человека, с которым разговариваете, но ваш партнер может вас услышать. Преимущество полудуплекса в том, что одинарный путь дешевле, чем двойной.
Полный дуплекс
- Относится к передаче данных в двух направлениях в одном соединении.
Независимо от этого дерьма есть способ получше - это веб-узлы HTML5
- Полный дуплекс
- Одно длительное соединение
- Соединение обновлено с HTTP
- Эффективное использование полосы пропускания и ЦП
Чтобы установить соединение WebSocket, клиент отправляет запрос установления связи WebSocket, для которого сервер возвращает ответ подтверждения связи WebSocket, как показано в примере ниже.
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
Ответ сервера:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
Как только веб-сокет установлен
- Обе стороны уведомили, что розетка открыта.
- Кадры передаются вперед и назад.
- Любая сторона может отправлять сообщения в любое время.
- Любая сторона может закрыть розетку.
Важно отметить, что WebSockets преобразует свое HTTP-соединение в соединение WebSocket. Другими словами, соединение WebSocket использует HTTP только для первоначального рукопожатия (для авторизации и аутентификации), после чего TCP-соединение используется для отправки данных по собственному протоколу.
WebSocket поддерживается не всеми браузерами, поскольку они периодически выпускаются, а socket.io работает как координатор между упомянутыми методами (длительный опрос, потоковая передача и т. Д.) На основе совместимости браузера.
Некоторые фотографии взяты с сайта https://blog.stanko.io/do-you-really-need-websockets-343aed40aa9b