Сеть в значительной степени построена вокруг парадигмы HTTP запрос / ответ. Клиент загружает веб-страницу, и тогда ничего не происходит, пока пользователь не перейдет на следующую страницу. Приблизительно в 2005 году AJAX начал делать интернет более динамичным. Тем не менее, все HTTP-коммуникации управляются клиентом, что требует взаимодействия с пользователем или периодического опроса для загрузки новых данных с сервера.
Технологии, позволяющие серверу отправлять данные клиенту в тот самый момент, когда он узнает, что новые данные доступны, существуют уже довольно давно. Они идут под такими именами, как «Push» или «Comet» .
При длительном опросе клиент открывает HTTP-соединение с сервером, которое остается открытым до отправки ответа. Всякий раз, когда на сервере действительно появляются новые данные, он отправляет ответ. Длинный опрос и другие методы работают довольно хорошо. Тем не менее, все они имеют одну общую проблему: они несут накладные расходы на HTTP, что не делает их подходящими для приложений с низкой задержкой. Например, многопользовательская стрелялка в браузере или любая другая онлайн-игра с компонентом реального времени.
Внедрение сокетов в сеть
Спецификация Web Socket определяет API, устанавливающий «сокетные» соединения между веб-браузером и сервером. С точки зрения непрофессионала, между клиентом и сервером существует постоянная связь, и обе стороны могут начать отправку данных в любое время.
Соединение через веб-сокет может быть просто открыто с помощью конструктора —
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
ws — это новая схема URL для соединений WebSocket. Существует также wss , для безопасного соединения WebSocket точно так же, как https используется для безопасных соединений HTTP.
Непосредственное подключение некоторых обработчиков событий к соединению позволяет узнать, когда соединение открыто, получены входящие сообщения или произошла ошибка.
Второй аргумент принимает необязательные подпротоколы . Это может быть строка или массив строк. Каждая строка должна представлять имя подпротокола, а сервер принимает только один из переданных подпротоколов в массиве. Принятый подпротокол может быть определен путем доступа к свойству протокола объекта WebSocket.
// When the connection is open, send some data to the server connection.onopen = function () { connection.send('Ping'); // Send the message 'Ping' to the server }; // Log errors connection.onerror = function (error) { console.log('WebSocket Error ' + error); }; // Log messages from the server connection.onmessage = function (e) { console.log('Server: ' + e.data); };
Общение с сервером
Как только у нас будет соединение с сервером (когда вызывается событие open), мы можем начать отправку данных на сервер, используя метод send (ваше сообщение) для объекта соединения. Раньше он поддерживал только строки, но в последней спецификации теперь он также может отправлять двоичные сообщения. Для отправки двоичных данных используется объект Blob или ArrayBuffer.
// Sending String connection.send('your message'); // Sending canvas ImageData as ArrayBuffer var img = canvas_context.getImageData(0, 0, 400, 320); var binary = new Uint8Array(img.data.length); for (var i = 0; i < img.data.length; i++) { binary[i] = img.data[i]; } connection.send(binary.buffer); // Sending file as Blob var file = document.querySelector('input[type = "file"]').files[0]; connection.send(file);
Точно так же сервер может отправлять нам сообщения в любое время. Всякий раз, когда это происходит, срабатывает обратный вызов onmessage. Обратный вызов получает объект события, и фактическое сообщение доступно через свойство data
.
WebSocket также может получать двоичные сообщения в последней спецификации. Двоичные кадры могут быть получены в формате Blob или ArrayBuffer. Чтобы указать формат полученного двоичного файла, задайте для свойства binaryType объекта WebSocket значение «blob» или «arraybuffer». Формат по умолчанию — blob.
// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer' connection.binaryType = 'arraybuffer'; connection.onmessage = function(e) { console.log(e.data.byteLength); // ArrayBuffer object if binary };
Еще одна новая функция WebSocket — это расширения. Используя расширения, можно будет отправлять сжатые, мультиплексированные кадры и т. Д.
// Determining accepted extensions console.log(connection.extensions);
Общение по происхождению
Будучи современным протоколом, связь между источниками запекается прямо в WebSocket. WebSocket позволяет общаться между сторонами в любом домене. Сервер решает, сделать ли свою службу доступной для всех клиентов или только для тех, которые находятся в наборе четко определенных доменов.
Прокси-серверы
Каждая новая технология сопровождается новым набором проблем. В случае с WebSocket это совместимость с прокси-серверами, которые обеспечивают HTTP-соединения в большинстве сетей компании. Протокол WebSocket использует систему обновления HTTP (которая обычно используется для HTTP / SSL), чтобы «обновить» соединение HTTP до соединения WebSocket. Некоторым прокси-серверам это не нравится, и соединение обрывается. Таким образом, даже если данный клиент использует протокол WebSocket, установление соединения может оказаться невозможным. Это делает следующий раздел еще более важным 🙂
Сторона сервера
Использование WebSocket создает совершенно новый шаблон использования для приложений на стороне сервера. Хотя традиционные серверные стеки, такие как LAMP, разрабатываются в соответствии с циклом HTTP-запросов / ответов, они часто плохо справляются с большим количеством открытых соединений WebSocket. Для одновременного сохранения большого количества соединений требуется архитектура, которая обеспечивает высокий параллелизм при низкой производительности.