Асинхронный веб, или Что такое веб-сокеты

Защита подключения с помощью TLS/SSL

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

Схема универсального кода ресурса (URI) Цель
wss: Используется для защищенных соединений, которые должны быть зашифрованы.
ws: Используется для незашифрованных соединений.

Чтобы зашифровать подключение WebSocket, воспользуйтесь схемой URI wss:. Ниже приведен пример.

Видео

Преимущества веб-сокета

Web Socket решает несколько проблем с REST или HTTP в целом —

Двунаправленный

HTTP — это однонаправленный протокол, в котором клиент всегда инициирует запрос. Сервер обрабатывает и возвращает ответ, а затем клиент использует его. Web Socket — это двунаправленный протокол, в котором нет предопределенных шаблонов сообщений, таких как запрос / ответ. Либо клиент, либо сервер могут отправить сообщение другой стороне.

Полный дуплекс

HTTP позволяет сообщению запроса перейти от клиента к серверу, а затем сервер отправляет ответное сообщение клиенту. В определенный момент времени клиент общается с сервером или сервер общается с клиентом. Web Socket позволяет клиенту и серверу общаться независимо друг от друга.

Одно TCP соединение

Как правило, новое соединение TCP инициируется для HTTP-запроса и прекращается после получения ответа. Необходимо установить новое TCP-соединение для другого HTTP-запроса / ответа. Для Web Socket HTTP-соединение обновляется с использованием стандартного механизма обновления HTTP, и клиент и сервер обмениваются данными через одно и то же TCP-соединение для жизненного цикла соединения Web Socket.

На приведенном ниже графике показано время (в миллисекундах), необходимое для обработки N сообщений для постоянного размера полезной нагрузки.

  Вот необработанные данные, которые подают этот г

Вот необработанные данные, которые подают этот график —

  График и таблица, приведенные выше, показывают,

График и таблица, приведенные выше, показывают, что издержки REST возрастают с увеличением количества сообщений. Это верно, потому что многие TCP-соединения должны быть инициированы и разорваны, а многие HTTP-заголовки должны быть отправлены и получены.

Последний столбец, в частности, показывает коэффициент умножения для количества времени для выполнения запроса REST.

На втором графике показано время, необходимое для обработки фиксированного количества сообщений путем изменения размера полезной нагрузки.

  Вот необработанные данные, которые подают этот г

Вот необработанные данные, которые подают этот график —

  Этот график показывает, что дополнительные затра

Этот график показывает, что дополнительные затраты на обработку запроса / ответа для конечной точки REST минимальны, и большую часть времени тратится на инициацию / завершение соединения и соблюдение семантики HTTP.

Заключение

Web Socket — это протокол низкого уровня. Все, в том числе простой шаблон запроса / ответа, как создавать / обновлять / удалять ресурсы, коды состояния и т. Д., Которые будут построены на его основе. Все они хорошо определены для HTTP.

Web Socket — это протокол с отслеживанием состояния, тогда как HTTP — это протокол без сохранения состояния. Соединения Web Socket могут масштабироваться вертикально на одном сервере, тогда как HTTP может масштабироваться горизонтально. Существует несколько проприетарных решений для горизонтального масштабирования Web Socket, но они не основаны на стандартах. HTTP поставляется с множеством других полезностей, таких как кэширование, маршрутизация и мультиплексирование. Все это должно быть определено поверх Web Socket.

Следующий программный код описывает работу приложения чата с использованием JavaScript и протокола Web Socket.

Пример

Рассмотрим прототип чата на WebSocket и Node.JS.

HTML: посетитель отсылает сообщения из формы и принимает в div

<!— форма для отправки сообщений —> <form name="publish"> <input type="text" name="message"> <input type="submit" value="Отправить"> </form> <!— здесь будут появляться входящие сообщения —> <div id="subscribe"></div>

Код на клиенте:

// создать подключение var socket = new WebSocket("ws://localhost:8081"); // отправить сообщение из формы publish document.forms.publish.onsubmit = function() { var outgoingMessage = ssage.value; socket.send(outgoingMessage); return false; }; // обработчик входящих сообщений socket.onmessage = function(event) { var incomingMessage = event.data; showMessage(incomingMessage); }; // показать сообщение в div#subscribe function showMessage(message) { var messageElem = document.createElement(‘div’); messageElem.appendChild(document.createTextNode(message)); document.getElementById(‘subscribe’).appendChild(messageElem); }

Серверный код можно писать на любой платформе. В нашем случае это будет Node.JS, с использованием модуля ws:

var WebSocketServer = new require(‘ws’); // подключённые клиенты var clients = {}; // WebSocket-сервер на порту 8081 var webSocketServer = new WebSocketServer.Server({ port: 8081 }); webSocketServer.on(‘connection’, function(ws) { var id = Math.random(); clients[id] = ws; console.log("новое соединение " + id); ws.on(‘message’, function(message) { console.log(‘получено сообщение ‘ + message); for (var key in clients) { clients[key].send(message); } }); ws.on(‘close’, function() { console.log(‘соединение закрыто ‘ + id); delete clients[id]; }); });

Рабочий пример можно скачать: websocket.zip. Понадобится поставить два модуля: npm install node-static && npm install ws.

Собственные механизмы защиты WebSocket

По умолчанию протокол WebSocket разработан для обеспечения безопасности. В реальном мире пользователь может столкнуться с различными проблемами, которые могут возникнуть из-за плохой реализации браузера. Со временем поставщики браузеров исправляют любые проблемы немедленно.

Дополнительный уровень безопасности добавляется при использовании безопасного соединения WebSocket через SSH (или TLS).

В мире WebSocket основной заботой является производительность защищенного соединения. Хотя еще есть дополнительный уровень TLS, сам протокол содержит оптимизации для этого вида использования, кроме того, WSS работает более гладко через прокси.

Маскировка клиент-сервер

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

Панель инструментов безопасности

Наконец, могут быть представлены полезные инструменты для исследования потока информации между клиентами и сервером WebSocket, анализа обмениваемых данных и выявления возможных рисков.

Инструменты разработчика браузера

Chrome, Firefox и Opera — отличные браузеры с точки зрения поддержки разработчиков. Их встроенные инструменты помогают нам определить практически любой аспект взаимодействия и ресурсов на стороне клиента. Это играет большую роль в целях безопасности.

Выпуск iPhone (первоначально) и iPad (позднее) представил совершенно новый мир веб-взаимодействия без необходимости использования веб-браузера. Вместо этого новые смартфоны и планшетные устройства использовали возможности собственных приложений, чтобы предложить уникальный пользовательский опыт.

Открытие соединений

Теперь, когда готов костяк приложения, можно начать изучать WebSocket API. Для начала узнаем, как создать новое соединение WebSocket. Для этого нужно вызвать конструктор класса WebSocket и передать ему URL сервера.

Скопируйте следующий код в файл app.js, чтобы создать новое соединение.

После того, как соединение установлено, возникнет событие open объекта WebSocket. Добавим обработчик события, который обновит статус элемента <div> сообщением о том, что соединение установлено.

Добавьте следующий код в файл app.js.

Также мы добавляем класс open элементу <div>.

Установка соединения ответ сервера

Ответ сервера на установку соединения веб сокетов, также выглядит, как ответ по протоколу http. Код ответа 101, переключение протоколов.

В заголовке  Upgrade, также указывается протокол н

В заголовке Upgrade, также указывается протокол на который происходит переключение web сокеты и  указывается ключ безопасности, который получен на основе ключа отправленного клиентам по специальному алгоритму описанному в документе RFC 6455. После этого между клиентом и сервером устанавливается прямое tcp соединение по котором данные передаются уже без использования протокола http.

Что такое веб-сокеты?

Веб-сокеты — новый путь для клиентов, чтобы связываться с сервером и наоборот без лишних http заголовков. Веб-сокеты используют свой собственный протокол, который был определен IETF. Последняя версия — RFC 6455. Предыдущие версии протокола доказали, что он имеет некоторые проблемы безопасности, поэтому он был реализован в некоторых браузерах, как Opera, но не был включен по умолчанию. Новые версии протокола, кажется, решили эти проблемы, и браузеры работают над его поддержкой в настоящее время.

Помимо своего протокола, веб-сокеты также имеют свой API, который может быть использован в веб-приложениях, чтобы открыть или закрыть соединение и посылать/получать сообщения. Он называется WebSockets API и определен в спецификации W3C.

С веб-сокетами вы можете использовать двунаправленную полную дюплексную связь между сервером и клиентом с минимальными накладными расходами по сравнению с обычным http. Веб-сокеты обещают быструю, более масштабируемую и более прочную высокую производительность приложений в реальном времени. На самом деле, по некоторым анализам Kaazing корпорации, это может уменьшить размер трафика заголовков http от 500:1 до 1000:1 и уменьшить задержки в сети до 3:1. Это приводит к серьезному повышению производительности, особенно для приложений, требующих быстрого обновления в реальном времени.

Формат заголовка кадра Web сокетов

Заголовок кадра в веб сокетах выглядит вот таким образом. Эта картинка из документа rfc.

Основные поля здесь это код операции (opcode),  ко

Основные поля здесь это код операции (opcode), который говорит о том, что за тип кадра. Это может быть кадр, который передает текстовые данные, бинарные данные, кадр ping, pong, close и другие типы кадров.

В разделе Payload Data находится полезные данные, которые нужно передать. В веб сокетах для того чтобы снизить накладные расходы используется хитрая схема для указания объема передаваемых данных. Если объем данных небольшой, то для поля длина данных используется всего лишь 7 бит, а если объем данных больше, то могут использоваться дополнительные биты заголовка и размер поля длина данных может быть 16 или 64 бита.

В первой части кадра находятся флаги. Первый вид флаг FIN используются для указания фрагментации, если этот флаг равен единице. то значит текущий кадр является последним. при этом если данные поместились в один кадр целиком и фрагментации нет. то флаг FIN установлен в единицу. 

А если данные были фрагментированны и передаются в нескольких кадрах, то во всех кадрах кроме последнего фланг FIN установлен в 0. Следующие три флага, зарезервированны и используются для расширения протокола веб советов. О том будут ли использоваться расширение и какие именно клиенту и серверу необходимо договориться в процессе установки соединения.

В веб сокетах данные при передаче могут маскироваться и на практике это делается почти всегда, если данные маскируются то флаг MASK установлен в единицу, в противном случае в 0. Если используется маскирование данных, то кадр должен включать ключ маскирование, Masking-key.

Ключ маскирование генерируется отправителем случайным образом и этот ключ должен быть разным для каждого кадра, если используются маскирование, то в части Payload Data находятся данные, которые получены в результате операции xor ключа маскирования и оригинальных данных.

Дополнительные параметры для MessageWebSocket и StreamWebSocket

Прежде чем устанавливать подключение, можно задать дополнительные параметры в сокете, задав свойства в MessageWebSocketControl или StreamWebSocketControl. Вы осуществляете доступ к экземпляру этих классов из самого объекта сокета через его свойство MessageWebSocket.Control или StreamWebSocket.Control в зависимости от ситуации.

Вот пример использования StreamWebSocket. Такая же схема применяется к MessageWebSocket.

Примечание. Не пытайтесь изменить свойство элемента управления после вызова ConnectAsync. Единственное исключение из этого правила — ssageType.

Реализация сервера на PHP

Исходники простого WebSocket echo-сервера выложил сюда. Код хорошо документирован, но я всё же опишу некоторые тонкости реализации. Чтобы «поднять» WebSocket сервер нужно создать обычный TCP-сервер. В PHP TCP-сервер реализуется через «stream_socket» или через PHP расширение «sockets». Различия между ними в том, что «stream_socket» работает на встроенных функциях PHP для работы с потоками, «sockets» же работает через модуль PHP и повторяет функции для работы с сокетами в языке «C». Я выбрал «sockets».

Процесс реализован через «while» с задержкой 0.2 секунды. Процесс не форкается и сообщения выбрасывает в консоль, поэтому запускать необходимо только через консоль. Для того, чтобы обслуживать несколько клиентов одновременно, сокет делаю неблокирующим и через «socket_select» каждые 0.2 секунды прослушиваю сокет. При рукопожатии проверяю только наличие заголовков.

Фреймы парсю через «pack/unpack». Сервер не понимает фрагментированных фреймов. Сервер выдаёт только незамаскированные сообщения, т.к. некоторые браузеры не понимают замаскированных сообщений. Сервер реагирует только на текстовые фреймы и фрейм закрытия соединения, бинарные фреймы не понимает.

Ну собственно всё, удачи в исследовании этого не простого протокола.

Теги

Adblock
detector