Учебники

WebSockets — общение с сервером

Сеть в значительной степени построена вокруг парадигмы 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. Для одновременного сохранения большого количества соединений требуется архитектура, которая обеспечивает высокий параллелизм при низкой производительности.