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

Сеть в значительной степени построена на парадигме запроса / ответа HTTP. Клиент загружает веб-страницу, а затем ничего не происходит, пока пользователь не перейдет на следующую страницу. Примерно в 2005 году AJAX начал делать Интернет более динамичным. Тем не менее, вся связь HTTP управляется клиентом, что требует взаимодействия с пользователем или периодического опроса для загрузки новых данных с сервера.

Технологии, которые позволяют серверу отправлять данные клиенту в тот самый момент, когда он знает, что новые данные доступны, существуют уже довольно давно. Они носят такие имена, как"Push" или же “Comet”.

С участием long polling, клиент открывает HTTP-соединение с сервером, которое остается открытым до отправки ответа. Каждый раз, когда на сервере появляются новые данные, он отправляет ответ. Длинный опрос и другие методы работают достаточно хорошо. Однако у всех них есть одна проблема: они несут накладные расходы HTTP, что не делает их подходящими для приложений с низкой задержкой. Например, многопользовательский шутер в браузере или любая другая онлайн-игра с компонентом реального времени.

Вывод сокетов в Интернет

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

Соединение с веб-сокетом можно просто открыть с помощью конструктора -

var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);

ws- это новая схема URL-адресов для подключений WebSocket. Есть такжеwss, для безопасного соединения WebSocket таким же образом https используется для безопасных HTTP-соединений.

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

Второй аргумент принимает необязательный subprotocols. Это может быть строка или массив строк. Каждая строка должна представлятьsubprotocol имя и сервер принимает только одно из переданных subprotocolsв массиве. Принятыйsubprotocol можно определить путем доступа к свойству протокола объекта 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. Для одновременного поддержания большого количества открытых соединений требуется архитектура, обеспечивающая высокий уровень параллелизма при низких затратах на производительность.