Обзор
Эта статья является четвертой главой протокола WebSocket.Основным содержанием, переведенным в этой статье, является содержание соединения WebSocket и рукопожатия, которое в основном включает в себя содержание рукопожатия между клиентом и сервером, а также то, как обе стороны взаимодействуют со связанными полями и логикой.
4 Начать рукопожатие (тело протокола)
4.1 Требования клиента
Чтобы установить соединение WebSocket, клиенту необходимо установить соединение и отправить протокол рукопожатия, как определено в этом разделе. Начальное состояние соединенияCONNECTING
. Клиент должен указать хост, порт, имя ресурса и безопасные поля, которые обсуждались в главе 3, а также список протоколов и расширений, которые можно использовать. Кроме того, если клиент является веб-браузером, необходимо указать поле источника.
Клиенты, работающие в контролируемой среде, например с использованием мобильного браузера конкретного оператора, могут отключиться и переключиться на других операторов. В этом случае нам необходимо рассмотреть назначенных клиентов, включая программное обеспечение для мобильных телефонов и соответствующих операторов.
Когда клиент передает ряд полей конфигурации (хост, порт, имя ресурса и безопасность) и список протоколов и расширений, которые можно использовать. Чтобы установить соединение WebSocket, он должен установить соединение, отправив протокол рукопожатия и получив рукопожатие. ответ от сервера. Что необходимо для установления соединения, какие поля будут отправлены при запуске рукопожатия, и как обрабатывать и интерпретировать ответ сервера, будет дан ответ в этом разделе. В следующем содержании мы будем использовать некоторые термины, определенные в главе 3, такие как поля host (хост) и secure (защищенные).
-
Поля, переданные в части URI WebSocket (хост, порт, имя ресурса и безопасность), должны быть допустимыми полями, указанными в разделе URI WebSocket в главе 3. Если какая-либо часть является недопустимым полем, клиент должен закрыть соединение на следующем шаге. .
-
Если у клиента есть соединение WebSocket с установленным соединением, определенным хостом, и портом, определенным удаленным хостом (IP-адресом), клиент должен дождаться текущего соединения, даже если удаленный хост определен другим именем. устанавливается только в случае успеха или неудачи учреждения. У клиента есть не более одного соединения, которое может быть
CONNECTING
условие. Если несколько подключений пытаются одновременно подключиться к одному и тому же IP-адресу, клиент должен отсортировать их так, чтобы только одно подключение могло выполнять следующие шаги.Если клиент не может определить IP-адрес удаленного хоста (например, все запросы проходят через прокси-сервер, который выполняет собственный поиск DNS), то клиент ДОЛЖЕН предположить, что каждое имя хоста соответствует другому удаленному хосту, поэтому клиент количество одновременных подключений должно быть ограничено разумно небольшим числом (например, клиент может разрешить одновременный
a.example.com
а такжеb.example.com
Эти два адреса устанавливают соединение, но если к хосту одновременно тридцать подключений, это может быть запрещено). Например, в среде веб-браузера клиенту необходимо установить ограничение на количество одновременных подключений, установленных на нескольких вкладках, открытых пользователем.Примечание. Это ограничение усложняет выполнение скриптами атак типа «отказ в обслуживании» просто за счет создания большого количества подключений WebSocket. Сервер может остановить атаку перед закрытием соединения, чтобы еще больше снизить нагрузку, что снизит скорость повторного подключения клиента.
Примечание. Количество соединений WebSocket, которые клиент может установить с одним хостом, не ограничено. Когда установлено слишком много соединений, сервер может отказаться от соединения, установленного с хостом/IP-адресом, а также сервер может активно отключать соединение, которое занимает ресурсы, когда нагрузка слишком высока.
-
Использовать прокси: если клиент использует настроенный прокси при использовании протокола WebSocket для подключения к определенному хосту и порту, то клиент должен подключиться к этому прокси и установить TCP-соединение через этот прокси с указанным хостом и портом.
Например, если клиент использует глобальный прокси-сервер HTTP, то при попытке установить соединение с портом 80 сайта example.com на прокси-сервер могут быть отправлены следующие поля:
CONNECT example.com:80 HTTP/1.1 Host: example.com
如果有密码字段的话,那么可能如下所示:
CONNECT example.com:80 HTTP/1.1 Host: example.com Proxy-authorization: Basic ZWRuYW1vZGU6bm9jYXBlcyE=
Если клиент не настроен с прокси, то должно быть установлено прямое TCP-соединение с заданным хостом и портом.
Примечание. Если возможно, при реализации прокси-сервера, который не предоставляет очевидный интерфейс для выбора прокси-сервера для WebSocket отдельно от других прокси-серверов, рекомендуется использовать SOCKS5 (RFC1928) прокси-сервер для соединений WebSocket, если это не работает, используйте прокси-сервер, настроенный для соединений HTTPS через соединения HTTP.
Для автоматической настройки сценария URI, переданный в качестве параметра, должен содержать хост, порт, имя ресурса и безопасные поля, определенные в разделе 3 URI WebSocket.
Примечание. Протокол WebSocket можно настроить на сценарий автоматической настройки прокси-сервера в соответствии с определенной спецификацией («ws» для незашифрованных подключений, «wss» для зашифрованных подключений).
-
Если соединение не открывается либо из-за сбоя прямого соединения, либо из-за того, что прокси-сервер возвращает ошибку, тогда клиент ДОЛЖЕН отключить соединение WebSocket и прекратить повторные попытки соединения.
-
Если присутствует безопасное поле, клиент ДОЛЖЕН выполнить рукопожатие TLS после установления соединения и перед отправкой данных рукопожатия. Если рукопожатие TLS не удается (например, сервер не проверяет положительное число), клиент ДОЛЖЕН отключить соединение WebSocket. В противном случае весь последующий трафик данных по этому каналу должен передаваться по зашифрованному каналу.
Клиенты ДОЛЖНЫ использовать расширение Server Name Indication (SNI) во время рукопожатия TLS.
Как только соединение с сервером установлено (либо через прокси-сервер, либо через зашифрованный канал TLS), клиент ДОЛЖЕН отправить пакет на сервер, чтобы инициировать рукопожатие. Этот пакет состоит из HTTP-запроса на обновление, содержащего ряд обязательных и необязательных полей заголовка. Конкретные требования к рукопожатию следующие:
-
рукопожатие должно бытьRFC2616Указанный допустимый HTTP-запрос.
-
Метод запроса должен быть GET, а версия HTTP должна быть не ниже 1.1.
Например: если URI WebSocket — «ws://example.com/chat», то первая строка заголовка отправленного запроса должна быть «GET /chat HTTP/1.1».
-
Часть «Request-URI» запроса ДОЛЖНА соответствовать имени ресурса, определенному в главе 3, или ДОЛЖНА быть URI абсолютного пути http/https, который при анализе URI имеет имя ресурса, хост (хост) и порт ( порт) соответствуют соответствующему файлу ws/wss.
-
Запрос должен содержать
Host
Поле заголовка, которое содержит поле хоста (хост) плюс поле порта (порта) сразу после «:» (используется порт по умолчанию, если порт не существует). -
Этот запрос должен содержать
Upgrade
поле заголовка, его значение должно содержать «websocket». -
Запрос должен содержать
Connection
поле заголовка, его значение должно содержать «Upgrade». -
Запрос должен содержать
Sec-WebSocket-Key
поле заголовка. Значение этого поля заголовка должно быть случайно сгенерированным 16-байтовым случайным числом с помощью base64 (см.Глава 4 RFC4648) закодировано. Каждое соединение должно выбирать случайное число.Примечание. Например, если порядок байтов случайно выбранного значения равен 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, то значение поля заголовка должно быть «AQIDBAUGBwgJCgsMDQ4PEC==".
-
Если запрос исходит от браузера, запрос должен содержать
Origin
поле заголовка. Если запрос исходит от клиента, не использующего браузер, запрос может также включать это поле, если семантика клиента соответствует семантике в примере. Значение этого поля заголовка является результатом сериализации ASCII исходного адреса исходного кода, установившего соединение. пройти черезRFC6454Можно узнать, как построить это значение.Например, если код в домене www.example.com пытается установить соединение с адресом ww2.example.com, значение этого поля заголовка должно быть "www.example.com".
-
Этот запрос должен содержать
Sec-WebSocket-Version
поле. Значение этого поля заголовка должно быть 13.ПРИМЕЧАНИЕ. Хотя все черновые версии этого документа (09, 10, 11 и 12) были опубликованы (эти протоколы в основном представляют собой редакционные изменения и пояснения, а не изменения в беспроводных протоколах), 9, 10, 11, 12 это четыре значения. не считаются действительными
Sec-WebSocket-Version
ценность . Эти значения зарезервированы IANA, но не используются и не будут использоваться в будущем. -
Этот запрос может содержать
Sec-WebSocket-Protocol
поле заголовка. Если оно присутствует, это значение содержит один или несколько подпротоколов, разделенных запятыми, которые клиент хочет использовать, упорядоченных по весу. Значение этих подпротоколов должно быть непустой строкой с символами в диапазоне от U+0021 до U+007E, за исключением определенных вRFC2616разделитель в , и каждый протокол должен быть уникальной строкой. Значение этого поля заголовка ABNF находится вRFC26161#токен, определяющий конструктор и правила. -
Этот запрос может содержать
Sec-WebSocket-Extensions
Поле.如果存在这个字段,这个值表示客户端期望使用的协议级别的扩展。这个header字段的具体内容和格式具体见9.1节。 -
Запрос может также содержать другие поля заголовка, определенные в документе, такие как файлы cookie (RFC6265) или поля заголовка, связанные с аутентификацией, такие как
Authorization
поле (RFC2616).
После того, как клиентский запрос подтверждения отправлен, клиент должен дождаться ответа сервера, прежде чем отправлять последующие данные. Клиент ДОЛЖЕН проверить запрос сервера по следующим правилам:
- Если клиент получает от сервера код состояния, отличный от 101, ему необходимо обрабатывать ответ каждого HTTP-запроса. В частности, клиенту может потребоваться пройти аутентификацию при получении кода состояния 401; сервер может перенаправить клиента через код состояния 3xx (но клиент не требует их соблюдения) и т. д. В противном случае выполните следующие действия.
- Если в ответе, полученном клиентом, отсутствует
Upgrade
поле заголовка илиUpgrade
Поле заголовка содержит значение, отличное от «websocket» (значение не чувствительно к регистру), тогда клиент ДОЛЖЕН закрыть соединение. - Если в ответе, полученном клиентом, отсутствует
Connection
поле заголовка илиConnection
Поле заголовка не содержит значение «Обновление» (значение не чувствительно к регистру), тогда клиент ДОЛЖЕН закрыть соединение. - Если клиент получает
Sec-WebSocket-Accept
поле заголовка илиSec-WebSocket-Accept
Поле заголовка не равно пройтиSec-WebSocket-Key
Значение поля (в виде строки, а не после декодирования base64) объединяется с "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", игнорируя все начальные и конечные пробелы для кодирования значения base64 SHA-1, после чего клиент ДОЛЖЕН закрыться. связь. - Если ответ, полученный клиентом, содержит
Sec-WebSocket-Extensions
поле заголовка, и значение расширения, используемое в этом поле, не существует в клиентском запросе установления связи (то есть сервер использует значение, которого нет в клиентском запросе), то клиент должен закрыть соединение. (Анализ этого поля заголовка для определения используемого расширения обсуждается в Разделе 9.1.) - Если ответ, полученный клиентом, содержит
Sec-WebSocket-Protocol
поле заголовка, и это поле содержит подпротокол, которого нет в рукопожатии клиента (то есть сервер использует значение, которое не существует в поле подпротокола в клиентском запросе), то клиент ДОЛЖЕН закрыть связь.
Если ответ не соответствует стороне обслуживания клиентов, определен в этом разделе, и раздел 4.2.2 определения требований ответа рукопожатия сервера, определенные, то клиент будет отключен.
Обратите внимание, что согласноRFC2616, все имена полей заголовков нечувствительны к регистру в HTTP-запросах и ответах на HTTP-запросы.
Если ответ сервера проходит описанный выше процесс проверки, значит, соединение WebSocket установлено, и получен статус соединения WebSocket.OPEN
условие. Используемое расширение определяется как строка (возможно, пустая), которая предоставляется, когда сервер отвечает на рукопожатие.Sec-WebSocket-Extensions
Значение поля или нулевое значение, если поле заголовка не существует в ответе на рукопожатие. Используемое значение подпротокола указывается в рукопожатии ответа сервера.Sec-WebSocket-protocol
Значение поля.Если у сервера нет этого поля заголовка в ответе на рукопожатие, то это значение также пусто. Кроме того, если ответ сервера на рукопожатие заключается в проверке поля заголовка любого файла cookie (определенного вRFC6265), эти файлы cookie называются файлами cookie, установленными во время рукопожатия открытия сервера (файлы cookie, установленные во время рукопожатия открытия сервера).
4.2 Требования к серверу
Сервер может смонтировать управление соединениями с другими сетевыми прокси, такими как балансировщики нагрузки или обратные прокси. В этом случае цель этой спецификации для сервера состоит в том, чтобы охватить все части инфраструктуры службы, начиная с цикла TCP-подключения первого устройства от установления до отключения и заканчивая приемом запроса сервером и отправкой ответа.
Пример. В центре обработки данных может быть сервер, который отвечает на запросы квитирования WebSocket, но передает все входящие кадры данных по соединению на другой сервер для обработки. В этом документе «сервер» включает в себя и то, и другое.
4.2.1 Анализ протокола рукопожатия клиента
Когда клиент запускает соединение WebSocket, он отправляет стартовый протокол рукопожатия. Чтобы получить необходимую информацию, чтобы гарантировать ответ сервера на рукопожатие, сервер должен проанализировать клиентскую часть протокола рукопожатия.
Протокол рукопожатия клиента состоит из следующих частей. Когда служба получает запрос квитирования, обнаруживается, что клиент не отправил протокол квитирования, который соответствует следующему содержимому (обратите внимание, что вRFC2616Для каждого элемента порядок полей заголовка не важен), включая, помимо прочего, недопустимый синтаксис ANBF в протоколе рукопожатия, сервер ДОЛЖЕН немедленно прекратить обработку запроса рукопожатия клиента и вернуть ошибку в ответе.Код ошибки HTTP (например, 400 Bad Request).
- Запрос HTTP/1.1 или более поздней версии GET, содержащий поле Request-URI, определенное в главе 3, которое должно быть разрешено в имя ресурса (или абсолютный путь HTTP/HTTPS, содержащий имя ресурса).
- включая разрешения сервера
Host
поле заголовка. - Нечувствительное к регистру значение "websocket"
Upgrade
поле заголовка. - Нечувствительное к регистру значение «Upgrade».
Connection
поле заголовка. - Значение кодировки Base64 (см.Глава 4 RFC4648) после длины 16 байт
Sec-WebSocket-Key
поле заголовка. - значение 13
Sec-WebSocket-Version
значение заголовка. - необязательный
Origin
поле заголовка. Все браузеры отправляют это поле. Соединения, в которых отсутствует это поле, не следует считать исходящими из браузера. - необязательный
Sec-WebSocket-Protocol
Поле заголовка, соответствующее значение — это подпротокол, поддерживаемый клиентом, отсортированный по весу. - необязательный
Sec-WebSocket-Extensions
Поле заголовка, соответствующее значение — это расширение, которое может использовать клиент. Конкретное содержание этого поля будет обсуждаться в разделе 9.1. - Необязательные другие поля, такие как использование файла cookie или поле для аутентификации запроса сервера. Нераспознанные поля заголовка будут основаны наRFC2616Контент игнорируется.
4.2.2 Отправить серверу запрос на подтверждение установления связи
Когда клиент и сервер устанавливают соединение WebSocket, сервер также должен выполнить шаги, описанные ниже, чтобы принять соединение и отправить серверу ответ подтверждения.
-
Если это соединение установлено на порту HTTPS (HTTPS+TLS), процесс рукопожатия TLS завершается по этой ссылке. Если это рукопожатие не удалось (например, клиент указал имя хоста в расширении «имя_сервера», но на сервере нет этого хоста), то закрываем соединение, в противном случае все последующие передачи данных по этому соединению (включая рукопожатие сервера) ответ) должен использовать зашифрованный канал.
-
Сервер может выбрать аутентификацию вне клиента, например, возвращая код состояния 401 иRFC2616соответствует описанию
WWW-Authenticate
поле заголовка. -
Сервер может использовать коды состояния 3xx (см.RFC2616) Перенаправить клиента. Обратите внимание, что этот шаг может выполняться до упомянутой выше аутентификации, а также аутентификации с или после.
-
Создайте следующую информацию:
источник(
origin
)Origin
Поле заголовка указывает в клиентском запросе установления связи, к какому источнику принадлежит сценарий, установивший соединение. Эта исходная информация сериализуется в ASCII и преобразуется в нижний регистр. Сервер может использовать эту информацию как часть справочного содержимого для принятия решения о принятии ссылки. Если сервер не фильтрует источники, он будет принимать подключения из любого источника. Если сервер не принимает соединение, он ДОЛЖЕН вернуть соответствующий код ошибки HTTP (например, 403 Forbidden) и завершить рукопожатие WebSocket, описанное в этом разделе. Подробнее читайте в главе 10.ключевое значение (
key
)Sec-WebSocket-Key
Поле заголовка представляет собой 16-байтовое значение в кодировке base64 в клиентском запросе установления связи. Это закодированное значение используется в процессе создания рукопожатия на стороне сервера для подтверждения принятия соединения. Серверу не нужноSec-WebSocket-Key
значение для декодирования. Версия(version
)Sec-WebSocket-Version
Поле заголовка в клиентском запросе установления связи указывает версию протокола WebSocket, используемого клиентом для установления соединения. Если эта версия не соответствует версии сервера, то сервер должен разорвать соединение WebSocket, описанное в этой главе, и отправить соответствующий код ошибки HTTP (например, 426 Требуется обновление) и вернутьSec-WebSocket-Version
Поле заголовка используется для идентификации номера версии, который может распознать сервер.имя ресурса(
resource name
)Идентификатор службы, предоставленный сервером. Если сервер предоставляет несколько сервисов, то это значение должно быть из поля Request-URI в методе GET клиентского рукопожатия. Если запрошенная служба поддерживает это, то сервер ДОЛЖЕН отправить соответствующий код ошибки HTTP (например, 404 Not Found) и завершить соединение WebSocket. подпротокол (
subprotocol
) Единое значение представительного подпротирации, используемого сервером, пустое. Это значение должно выбрать протокол рукопожатия клиентаSec-WebSocket-Protocol
Значение, указанное в поле, сервер будет использовать это значение (произвольное) в этом соединении. Если клиентский протокол рукопожатия не содержит этого поля или сервер не поддерживает ни один из подпротоколов, предоставленных в клиентском запросе, это значение может быть только пустым. Отсутствие этого значения заголовка говорит о том, что значение пустое (это означает, что сервер не может выбрать какой-либо подпротокол, переданный клиентом, и запрещается добавлять подпротокол в ответный запросSec-WebSocket-Protocol
поле). Пустая строка — это не то же самое, что нулевое значение, а нулевое значение — недопустимое значение для этого поля. ABNF может видеть определение и правила построения всего поляRFC2616.расширение (
extensions
)Представляет (может быть пустым) список расширений уровня протокола, которые сервер готов использовать. Если сервер поддерживает несколько расширений, то это значение должно быть существующим значением в рукопожатии клиента, начиная с
Sec-WebSocket-Extensions
字段中取一到多个值。该字段不存在时则表示此值为空。空字符串与空值不同。客户端没有列举的扩展静止被 использовать.应该选择哪些值和如何进行解析可以见9.1节。 -
Если сервер принимает решение принять соединение, он должен ответить, отправив допустимый HTTP-запрос, как описано ниже.
- картинаRFC2616Как поясняется в , строка состояния с кодом состояния 101. Например, это выглядит так: "HTTP/1.1 101 протоколы переключения".
- картинаRFC2616Как описано в, значение "websocket"
Upgrade
поле заголовка. - Значение "Обновить"
Connection
поле заголовка. - Один
Sec-WebSocket-Accept
поле заголовка. Это значение создается из ключа, упомянутого в шаге 4 раздела 4.2.2, путем объединения его со строкой «258EAFA5-E914-47DA-95CA-C5AB0DC85B11» для хеш-операции SHA-1, в результате чего получается хеш-раздел из 20 слов. значение, затем base64 кодирует эти 20 байтов. ABNF определяет это поле следующим образом:
Sec-WebSocket-Accept = base64-value-non-empty base64-value-non-empty = (1*base64-data [ base64-padding ]) | base64-padding base64-data = 4base64-character base64-padding = (2base64-character "==") | (3base64-character "=") base64-character = ALPHA | DIGIT | "+" | "/"
ПРИМЕЧАНИЕ. Например, если рукопожатие клиента отправляет
Sec-WebSocket-Key
Значение поля заголовка — «dGhlIHNhbXBsZSBub25jZQ==", тогда сервер соединит «258EAFA5-E914-47DA-95CA-C5AB0DC85B11», чтобы получить «dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11». Затем сервер выполняет хеш-операцию SHA-1 для этой строки, чтобы получить 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. Base64 кодирует это значение, чтобы получить результат "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", затем передайтеSec-WebSocket-Accept
поле возвращает этот результат. 5. ДополнительноSec-WebSocket-Protocol
Поле со значением, определенным в подпротоколе в пункте 4.2.2 пункта 4. 6. ДополнительноSec-WebSocket-Extensions
Поле определено в разделе 4.2.2, дополнении к пункту 4.
Это завершает ответ сервера на рукопожатие. Если сервер не закроет и не прервет соединение WebSocket после выполнения вышеуказанных шагов, тогда сервер рассмотрит возможность установления соединения WebSocket и установит статус соединения WebSocket наOPEN
. В этот момент сервер может начать отправлять (и получать) данные.
4.3 Соберите поля заголовка нового ABNF, используемого в рукопожатии
В этом разделе используетсяRFC2616, раздел 2.1Определены грамматики и правила ABNF, включая неявные правила *LWS.
Обратите внимание на использование положений ABNF в этом разделе. Некоторые имена правил соответствуют некоторым полям заголовка. Такое правило представляет значение соответствующего поля заголовка, например,Sec-WebSocket-Key
ABNF описываетSec-WebSocket-Key
Синтаксис значения поля заголовка. Правила ABNF с суффиксом «-Client» в имени применяются только к запросам, отправляемым клиентом на сервер, а правила ABNF с суффиксом «-Server» в имени применимы только к ответу на запрос, отправляемому сервером. клиенту. Например правила ABNFSec-WebSocket-Protocol-Client
Указывает, что в запросе, отправленном клиентом на серверSec-WebSocket-Protocol
значение поля.
Следующие новые поля заголовков можно использовать, когда клиент отправляет серверу запрос подтверждения:
Sec-WebSocket-Key = base64-value-non-empty
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Protocol-Client = 1#token
Sec-WebSocket-Version-Client = version
base64-value-non-empty = (1*base64-data [ base64-padding ]) | base64-padding
base64-data = 4base64-character
base64-padding = (2base64-character "==") | (3base64-character "=")
base64-character = ALPHA | DIGIT | "+" | "/"
extension-list = 1#extension
extension = extension-token *( ";" extension-param )
extension-token = registered-token
registered-token = token
extension-param = token [ "=" (token | quoted-string) ]
;当使用带引号的字符串语法变体时,在引号转义后面的值必须和ABNF"标记(token)"一致。
NZDIGIT = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
version = DIGIT | (NZDIGIT DIGIT) | ("1" DIGIT DIGIT) | ("2" DIGIT DIGIT)
; 范围是从0-255,没有前导0
Следующие новые поля заголовков можно использовать, когда сервер отправляет клиенту ответный запрос на рукопожатие:
Sec-WebSocket-Extensions = extension-list
Sec-WebSocket-Accept = base64-value-non-empty
Sec-WebSocket-Protocol-Server = token
Sec-WebSocket-Version-Server = 1#version
4.4 Поддержка нескольких версий протокола WebSocket
В этом разделе приведены некоторые рекомендации по поддержке нескольких версий протокола WebSocket между клиентами и серверами.
Отметьте поле версией WebSocket (Sec-WebSocket-Version
поле заголовка), клиент может выбрать номер версии протокола WebSocket при первоначальном запросе (клиент не обязан поддерживать последнюю версию). Если сервер поддерживает запрошенную версию и сообщение, которое я получаю, действительно, то сервер примет эту версию. Если сервер не поддерживает версию, запрошенную клиентом, сервер ДОЛЖЕН вернутьSec-WebSocket-Version
поле заголовка (или болееSec-WebSocket-Version
поле заголовка) содержит все версии, поддерживаемые сервером. В этом случае, если клиент поддерживает какую-либо версию, он МОЖЕТ выбрать новое значение версии, чтобы повторно инициировать запрос установления связи.
В следующем примере показано, как выполнить согласование версии, описанное выше:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 25
Ответ от сервера может выглядеть так:
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13, 8, 7
Обратите внимание, что окончательный ответ на запрос, отправленный сервером, также может выглядеть так:
HTTP/1.1 400 Bad Request
...
Sec-WebSocket-Version: 13
Sec-WebSocket-Version: 8, 7
Клиент выбирает версию 13 и повторно рукопожатия:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
...
Sec-WebSocket-Version: 13