Interested Article - WebSocket
- 2020-01-25
- 1
WebSocket — протокол связи поверх TCP -соединения, предназначенный для обмена сообщениями между браузером и веб-сервером, используя постоянное соединение.
В настоящее время в W3C осуществляется стандартизация API Web Sockets. Черновой вариант стандарта этого протокола утверждён IETF .
WebSocket разработан для воплощения в веб-браузерах и веб-серверах, но он может быть использован для любого клиентского или серверного приложения. Протокол WebSocket — это независимый протокол, основанный на протоколе TCP. Он делает возможным более тесное взаимодействие между браузером и веб-сайтом, способствуя распространению интерактивного содержимого и созданию приложений реального времени.
Открытие канала WebSocket
Для установления соединения WebSocket клиент и сервер используют протокол, похожий на HTTP . Клиент формирует особый HTTP-запрос, на который сервер отвечает определенным образом.
Протокол 75
До редакции черновика протокола номер от 8 июня 2010 на Wayback Machine включительно соединение WebSocket устанавливалось следующим образом. Запрос клиента:
GET /demo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
WebSocket-Protocol: sample
Ответ сервера, подтверждающий переход на WebSocket:
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
WebSocket-Protocol: sample
Сразу после отправки ответа WebSocket-соединение считается установленным, клиент и сервер могут начинать двунаправленный обмен сообщениями по этому же TCP -соединению. Для передачи текстового сообщения (в кодировке UTF-8 ) необходимо перед ним передать нулевой байт, а после — байт со значением 255.
Протокол 76
2 июня 2010 года в протокол WebSocket были внесены поправки, изменившие процедуру установления соединения WebSocket без сохранения обратной совместимости. В 19 апреля 2012 года. редакции черновика протокола WebSocket добавлена защита от поддельных запросов. Клиент, поддерживающий новую схему, присылает следующий запрос:
GET /demo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Key2: 4 @1 46546xW%0l 1 5
Host: example.com
Sec-WebSocket-Key1: 12998 5 Y3 1 .P00
Origin: http://example.com
WebSocket-Protocol: sample
^n:ds[4U
В запрос добавлены новые заголовки «Sec-WebSocket-Key1» и «Sec-WebSocket-Key2» и 8-байтовое тело запроса. Все они генерируются клиентом случайным образом.
Ответ сервера, подтверждающий переход на WebSocket:
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Location: ws://example.com/demo
Sec-WebSocket-Protocol: sample
8jKS'y:G*Co,Wxa-
Ответ содержит новые названия заголовков («Sec-WebSocket-Origin», «Sec-WebSocket-Location», «Sec-WebSocket-Protocol» вместо «WebSocket-Origin», «WebSocket-Location», «WebSocket-Protocol») и 16-байтное тело ответа, вычисляемое следующим образом:
- из строки со значением заголовка запроса Sec-WebSocket-Key1 исключить все символы, не являющиеся цифрами (не попадающие в диапазон '0'..'9');
- полученную строку превратить в 64-битное целое число (для примера выше получим 1299853100);
- полученное число разделить целочисленным делением на количество пробелов в исходной строке со значением заголовка;
- полученное число представить в виде 4-байтового 32-битного числа в формате big endian : старший байт хранится по нулевому смещению;
- проделать то же самое с заголовком Sec-WebSocket-Key2;
- интерпретируя числа из пунктов 4) и 5) как 4-байтовые строки, конкатенировать их (сложить в одну строку) и добавить как строку тело запроса;
- вычислить от полученной 16-байтной строки значение MD5 и записать это значение в тело ответа «как есть», без преобразования в какое-либо представление;
Примечания.
Несмотря на «похожесть» новых запросов и ответов на запросы и ответы протокола HTTP , они таковыми не являются. Например, в запросе есть тело, но в заголовках поле «Content-Length» отсутствует (что нарушает соглашения HTTP ).
Серверной части следует поддерживать оба вида клиентов и различать их по наличию или отсутствию в запросе заголовков Sec-WebSocket-Key1 и Sec-WebSocket-Key2.
Протокол 07
В 19 апреля 2012 года. черновика протокола от 22 апреля 2011 были внесены изменения.
В отличие от протокола 76, согласно которому данные передаются без шифрования , каждый байт передаваемых от клиента (браузера) серверу данных в этой версии протокола обязательно маскируется 4-байтовой маской . Она создается для каждого сообщения заново.
Передаваемое сообщение теперь имеет заголовок, в котором содержатся такие данные, как:
- фрагментировано ли сообщение;
- тип передаваемых данных;
- подвергалось ли сообщение маскировке;
- размер данных;
- маска;
- другие управляющие данные (ping, pong…).
Взаимодействие между клиентом и сервером начинается с запроса от клиента:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 7
Ответ сервера имеет следующий вид:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Ответ содержит заголовок Sec-WebSocket-Protocol с единственным протоколом, выбраным сервером (chat) из всех поддерживаемых клиентом (chat, superchat). Заголовок Sec-WebSocket-Accept формируется следующим образом:
- взять строковое значение из заголовка Sec-WebSocket-Key и объединить со строкой 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 (в приведённом примере получится dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11)
- вычислить бинарный хеш SHA-1 (бинарная строка из 20 символов) от полученной в первом пункте строки
- закодировать хеш в Base64 (s3pPLMBiTxaQ9kYGzzhZRbK+xOo=)
Пример реализации вышеуказанного алгоритма на языке PHP :
<?php
echo base64_encode(SHA1("dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
?>
Протокол (далее данные передаются фрэймами с использованием этого протокола)
11 декабря 2011 года протокол приобрел статус RFC .
Вместо заголовка Sec-WebSocket-Origin теперь используется просто Origin .
Схема URI
Протокол Web Socket определяет две URI -схемы, ws: (нешифрованное соединение) и wss: (шифрованное соединение).
Реализация WebSocket в браузерах
Для установки соединения клиентский скрипт создает объект WebSocket, в конструктор которого передает параметр WebSocket URI, и определяет функции обратного вызова при соединении, получении сообщения и разрыве соединения.
<html>
<head>
<script>
const webSocket = new WebSocket('ws://localhost/echo');
webSocket.onopen = event => {
alert('onopen');
webSocket.send("Hello Web Socket!");
};
webSocket.onmessage = event => {
alert('onmessage, ' + event.data);
};
webSocket.onclose = event => {
alert('onclose');
};
</script>
</head>
<body>
</body>
</html>
В настоящее время WebSocket поддерживается в следующих браузерах:
- Google Chrome (начиная с версии 4.0.249.0);
- Apple Safari (начиная с версии 5.0.7533.16);
- Mozilla Firefox (начиная с версии 4);
- Opera (начиная с версии 10.70 9067);
- Internet Explorer (начиная с версии 10);
Проверить поддержку браузером WebSocket можно, пройдя по ссылке: от 8 апреля 2017 на Wayback Machine .
В конце ноября 2010 Adam Barth опубликовал результаты исследования надежности используемого протокола . По его результатам выяснилось, что в случае использования прозрачных прокси-серверов возможна подмена кеша передаваемых данных с тем, что пользователи вместо реальных данных будут получать версию данных от злоумышленника. Проблема оказалась достаточно серьёзной для того, чтобы разработчики Firefox и Opera объявили о том, что в будущих версиях их браузеров поддержка веб-сокетов будет по умолчанию отключена вплоть до устранения проблемы небезопасности данного протокола (хотя осталась возможность их включить).
Примечания
- . Дата обращения: 20 сентября 2011. 19 апреля 2012 года.
- . Дата обращения: 20 сентября 2011. 19 апреля 2012 года.
- от 11 января 2011 на Wayback Machine
Ссылки
- от 8 января 2012 на Wayback Machine , стандарт протокола
- от 7 июня 2015 на Wayback Machine черновик спецификации W3C
- сайт, посвященный WebSocket (поддерживает тестовый эхо-сервер на WebSocket)
- от 7 октября 2010 на Wayback Machine сайт, проверяющий работу WebSockets и Comet в вашем браузере
- 2020-01-25
- 1