Раньше я отвечал за выполнение службы push-сообщений компании самостоятельно и сотрудничал с мобильным терминалом для выполнения таких функций, как вход в систему с кодом сканирования, push-сообщение о заказе и широковещательная рассылка сообщений о событиях. Чтобы углубить свое понимание протокола Websocket, я многому научился, перехватывая пакеты. Теперь поделитесь им, я надеюсь, что это может быть полезно для всех.
Консоль Chrome
(1) F12 входит в консоль, нажмите «Сеть», выберите столбец ws и обратите внимание, что выбран «Фильтр».
(2) При обновлении страницы будет получена ссылка ws.
(3) Щелкните ссылку, чтобы просмотреть сведения о ссылке
Обратите внимание на информацию, отмеченную в красной рамке, которая будет подробно объяснена позже. (4) Конечно, вы также можете переключиться на фреймы для просмотра отправленных и полученных сообщений, но это очень просто, вы можете видеть только содержание сообщения, длину данных и время.
Fiddler: инструмент для захвата и отладки пакетов
(1) Откройте Fiddler, нажмите «Правила» в строке меню и выберите «Настроить правила...».
(2) В это время будет открыт файл CustomRules.js, и в класс Handlers будет добавлен следующий код.
static function OnWebSocketMessage(oMsg: WebSocketMessage) {
// Log Message to the LOG tab
FiddlerApplication.Log.LogString(oMsg.ToString());
}
(3) После сохранения вы можете увидеть пакет данных WebSocket на вкладке «Журнал» в правом столбце Fiddler. Отмечено красным прямоугольником на следующем рисункеClient.1Представляет первое сообщение, отправленное клиентом; соответствующийServer.1Представляет первое сообщение, отправленное сервером. Тип сообщения:TextПредставляет обычное сообщение вызова;CloseСессия делегата закрыта. Сообщение от клиента:
Сообщение от сервера:
Затем мы обнаружим, что каждое закрытие сеанса инициируется клиентом:
По сравнению с консолью Chrome, Fiddler захватывает пакеты более подробно: он может знать, отправлено ли сообщение сеанса клиентом или сервером, и может знать тип сообщения. Но это все еще не удовлетворяет цели глубокого понимания и изучения протокола Websocket. Если вы имеете дело с HTTP, HTTPS или используете Fiddler. Другие протоколы, такие как TCP и UDP, используют WireShark. Протокол TPC/IP — это протокол транспортного уровня, который в основном решает, как данные передаются в сети, а HTTP и Websocket — это протоколы прикладного уровня, в основном решающие, как упаковывать данные. Поскольку прикладной уровень упаковывает данные на основе транспортного уровня, мы все же начнем с самого низа, чтобы понять, что такое Websocket и как он работает.
WireShark
WireShark (ранее Ethereal) — программа для анализа сетевых пакетов. Функция программного обеспечения для анализа сетевых пакетов заключается в захвате сетевых пакетов и отображении максимально подробных данных о сетевых пакетах. Перехват пакетов WireShark основан на пятиуровневом протоколе TCP/IP, то есть на физическом уровне, канальном уровне, сетевом уровне, транспортном уровне и прикладном уровне. В основном мы фокусируемся на транспортном уровне и прикладном уровне.
Трехстороннее рукопожатие TCP
Все мы знаем, что когда TCP устанавливает соединение, происходит трехсторонний процесс рукопожатия. На следующем рисунке показаны три пакета данных трехэтапного рукопожатия, перехваченные WireShark (хотя он и называется пакетом данных, пакет трехэтапного рукопожатия не содержит данных).
Нажмите на пакеты данных на рисунке выше, чтобы просмотреть сведения о каждом пакете данных.Здесь нам нужно прояснить несколько понятий, чтобы понять, что означает каждый пакет данных:SYN:бит синхронизации, установить соединение.ACK:бит подтверждения, установите 1, чтобы указать, что это TCP-пакет подтверждения, 0, чтобы не указывать.PSH:биты, когда отправитель PSH=1, получатель должен передать его процессу приложения как можно скорее.
- первое рукопожатие
Вы можете видеть, что протокол управления передачей, который мы открыли, является транспортным уровнем (Tcp). SYN устанавливается равным 1, и клиент отправляет серверу пакет запроса на подключение.
- второе рукопожатие
Сервер получает TCP-сообщение, отправленное клиентом, знает, что клиент запрашивает установление соединения с SYN=1, отправляет TCP-сообщение с SYN=1, ACK=1 клиенту и устанавливает порядковый номер подтверждения для клиента. порядковый номер плюс 1.
- третье рукопожатие
После того, как клиент получает пакет, отправленный сервером, он проверяет, правильный ли серийный номер, то есть серийный номер, отправленный в первый раз + 1, и равен ли бит флага ACK 1. Если это правильно, пакет подтверждения отправляется снова, а флаг ACK равен 1. Связь успешно установлена, и данные можно отправлять.
Специальный HTTP-запрос
За ним следует запрос Http (четвертый пакет), указывающий, что Http использует Tcp для установления соединения.
Давайте сначала посмотрим на транспортный уровень (Tcp): PSH (push-бит) установлен в 1, ACK установлен в 1, а PSH установлен в 1, чтобы начать отправку данных.В то же время ACK должен быть установлен в 1, когда отправке данных, потому что это должно быть подтверждено концом, получающим пакет данных. Когда PSH равен 1, он обычно появляется только в пакетах, содержимое DATA которых не равно 0. Другими словами, когда PSH равен 1, это означает, что существует реальное содержимое пакета данных TCP для передачи.
Давайте посмотрим на прикладной уровень (Http): это специальный Http-запрос, почему он специальный Http-запрос? Connection:Upgrade Upgrade:websocket в заголовке HTTP-запроса, Upgrade представляет обновление до более нового протокола Http или переключение на другой протокол. Понятно, что WebSocket использует этот механизм для установления соединения с HTTP-сервером совместимым образом. Протокол WebSocket состоит из двух частей: рукопожатие для установления обновленного соединения и фактическая передача данных. Во-первых, клиент запрашивает соединение WebSocket, используя заголовки Upgrade: WebSocket и Connection: Upgrade, а также некоторые заголовки, специфичные для протокола, чтобы установить используемую версию и настроить рукопожатие. Сервер, если он поддерживает протокол, отвечает теми же заголовками Upgrade: WebSocket и Connection: Upgrade и завершает рукопожатие. После завершения рукопожатия начинается передача данных. Эта информация также видна в предыдущей консоли Chrome.
просить:
отклик: код состояния ответа101Указывает, что сервер понял запрос клиента, и после отправки этого ответа сервер переключится на те протоколы, которые указаны в заголовке запроса на обновление.
Из этого мы можем сделать вывод: Протокол Websocket по сути является протоколом на основе TCP. Для установления соединения требуется рукопожатие.Клиент (браузер) сначала инициирует специальный http-запрос к серверу (веб-серверу), а веб-сервер анализирует его и формирует ответ для браузера.Таким образом, соединение по веб-сокету до тех пор, пока одна из сторон не закроет соединение.
Мир веб-сокетов
Формат протокола связи — формат WebSocket.Сервер использует Tcp Socket для получения данных и их разбора.Формат протокола следующий:
В первую очередь нам нужно знать, что данные находятся на физическом уровне, канальный уровень передаётся в бинарном виде, а на прикладном уровнешестнадцатеричныйБайтовые потоки передаются.
Первый байт:
FIN: 1 бит, используется для описания того, заканчивается ли сообщение, если он равен 1, сообщение является хвостом сообщения, если он равен нулю, существуют последующие пакеты данных;RSV1,RSV2,RSV3: 1 бит каждый, используемый для определения расширения, должен быть равен 0, если нет соглашения о расширенииOPCODE: 4 бита, используемые для указания типа приема сообщения, если получен неизвестный код операции, получатель должен закрыть соединение.
Определение OPCODE во фрейме данных Webdocket: 0x0 означает дополнительный фрейм данных 0x1 означает текстовый фрейм данных 0x2 означает кадр двоичных данных 0x3-7 временно не определен, зарезервирован для будущих неуправляющих кадров 0x8 означает, что соединение закрыто 0x9 означает пинг 0xA означает понг 0xB-F временно не определен, зарезервирован для будущих управляющих кадров
Второй байт:
MASKБит :1 используется для определения того, маскируются ли PayloadData.Кадр данных, отправляемый клиентом, должен быть замаскирован, поэтому этот бит равен 1. Данные необходимо расшифровать.PayloadDataДлина: 7 бит, 7+16 бит, 7+64 бит Если его значение 0-125, это истинная длина полезной нагрузки. Если значение равно 126, значение 16-битного целого числа без знака, образованного двумя последними байтами, является истинной длиной полезной нагрузки. Если значение равно 127, значение 64-битного целого числа без знака, образованного следующими 8 байтами, является истинной длиной полезной нагрузки.
Вышеприведенное изображение представляет собой пакет данных, отправленный клиентом на сервер, в котором длина PayloadData является двоичной: 01111110 -> десятичной: 126; если значение равно 126, значение 16-битного целого числа без знака формируется следующим образом два байта - это истинная длина полезной нагрузки. То есть шестнадцатеричное, обведенное красным: 00C1——>десятичное: 193 байта. Таким образом, фактическая длина данных PayloadData составляет 193 байта;
Согласно нашему анализу, диаграмма кадра веб-сокета пакета клиент-сервер должна быть:
Давайте перехватим пакеты и проанализируем пакеты данных от сервера к клиенту:
Можно обнаружить, что бит MASK во втором байте пакета данных, отправленного сервером клиенту, равен 0, что означает, что кадр данных, отправленный сервером, не был замаскирован. -сторонние данные нет. (Если сервер получает немаскированный пакет, отправленный клиентом, он автоматически отключается; наоборот, если клиент получает замаскированный пакет, отправленный сервером, он также автоматически отключается. ).
Обработка маски:
Немаскированная обработка:
Согласно нашему анализу, диаграмма кадра веб-сокета пакета «сервер-клиент» должна быть:
TCP KeepAlive
Как показано на рисунке выше, пакеты проверки активности TCP всегда отображаются парами, включая пакеты обнаружения проверки активности TCP и пакеты подтверждения обнаружения проверки активности TCP. Сообщение TCP об обнаружении активности представляет собой данные прикладного уровня, которые вычитают 1 из порядкового номера подтверждения предыдущего сообщения TCP и задают 1 байт, а содержимое равно «00», как показано на следующем рисунке:
Подтверждающее сообщение об обнаружении проверки активности TCP является подтверждением сообщения об обнаружении проверки активности.Формат сообщения следующий:
Т.к. Websocket работает через Tcp Socket, то теперь рассмотрим вопрос, при длинном соединении, как сервер узнает порядок сообщений? Это включает в себя серийный номер tcp (Sequence Number) и номер подтверждения (Acknowledgment Number).Насколько я понимаю, серийный номер — это длина отправленных данных; номер подтверждения — это длина полученных данных.. Это более абстрактно.Давайте начнем с трехэтапного рукопожатия TCP (в сочетании со следующим рисунком) и подробно разберем его.
пакет 1: Порядковый номер каждого конца сеанса TCP начинается с 0. Точно так же номер подтверждения также начинается с 0, потому что вызов еще не начался, а другой конец вызова должен быть подтвержден.
пакет 2: Сервер отвечает на запрос клиента порядковым номером 0 (поскольку это первый пакет, отправленный сервером в этом TCP-сеансе, поэтому порядковый номер равен 0) и относительным номером подтверждения 1 (указывающим, что сервер получил клиентский SYN в пакет 1 отправлен до конца). Следует отметить, что хотя клиент не отправил никаких достоверных данных, номер подтверждения все равно увеличивается на 1, поскольку полученный пакет содержит флаг SYN или FIN.
пакет 3: Как и в пакете 2, клиент отвечает на серийный номер сервера 0 номером подтверждения 1, и ответ также содержит собственный серийный номер клиента (поскольку пакет, отправленный сервером, подтверждает получение SYN, отправленного клиентом, клиент серийный номер терминала меняется с 0 на 1) В это время серийный номер обоих концов связи равен 1.
пакет 4: Клиент -> Сервер Это первый пакет в потоке, который несет действительные данные (точнее, HTTP-запрос, отправленный клиентом), порядковый номер по-прежнему равен 1, поскольку до последнего пакета данные не были отправлены, и номер подтверждения остается равным 1. без изменений, так как клиент не получает никаких данных от сервера. Следует отметить, что длина действительных данных в пакете составляет 505 байт.
пакет 5: сервер -> клиент Когда верхний уровень обрабатывает HTTP-запрос, сервер отправляет этот пакет для подтверждения данных, отправленных клиентом в пакете 4. Следует отметить, что значение числа подтверждения увеличивается на 505 (505 — эффективная длина данных в пакете 4), который становится 506, короче говоря, сервер использует это для информирования клиента. Пока я получил в общей сложности 506 байт данных, и серийный номер сервера остается неизменным на 1.
упаковка 6: сервер -> клиент Этот пакет отмечает начало ответа HTTP, возвращенного сервером, и порядковый номер по-прежнему равен 1, поскольку пакет, возвращенный сервером перед этим пакетом, не содержит действительных данных, а этот пакет содержит 129 байтов действительных данных.
пакет 7: В связи с отправкой последнего пакета данных порядковый номер подтверждения TCP-клиента увеличивается до 130, а от сервера принимается 129 байт данных, а число подтверждения клиента увеличивается с 1 до 130. Поняв, как работают серийный номер и серийный номер подтверждения, мы также знаем, почему «сообщение об обнаружении активности TCP должно вычесть 1 из серийного номера подтверждения предыдущего сообщения TCP и установить 1 байт». Один минус один плюс один — это гарантия того, что сохранение активности в соединении не влияет на серийный номер и серийный номер подтверждения. Данные 1 байта 00 в Keep Alive на самом деле не являются данными для передачи, а правилом TCP Keep Alive, широко известным как.
Суммировать: WebSocket — это независимый протокол на основе TCP, и единственная связь между ним и HTTP заключается в том, что его запрос подтверждения может быть интерпретирован сервером HTTP как запрос на обновление. Чтобы быть более строгим:WebSocket — это сетевой протокол связи. Если вы понимаете приведенный выше формат фрейма данных и процесс рукопожатия, вы можете осуществлять мгновенную связь на основе веб-сокета..
Публичный аккаунт WeChat: подпишитесь на официальный аккаунт, чтобы получать последние обновления