Недавно я изучал протокол rtmp. Меня всегда смущало чтение официальных документов. Прочитав их в течение двух дней, я теперь в основном понимаю протокол rtmp и хочу объяснить протокол rtmp так, как мне кажется. Надеюсь, это поможет мне понять это. Полезно для такого новичка, как я.
В этой статье протокол rtmp будет объяснен в следующих четырех частях.
Сообщение — это базовая единица данных RTMP. Сервер и клиент обмениваются данными, отправляя сообщения RTMP по сети. Сообщения могут содержать аудио, видео, данные или другие сообщения.
RTMPзаголовок сообщенияинагрузкадве части。
ценить | длина | значение |
---|---|---|
message type | 1byte | Указывает тип сообщения |
payload length | 3byte | Количество байтов, представляющих нагрузку,формат с прямым порядком байтов |
timestamp | 4byte | Представляет временную метку сообщения в формате с обратным порядком байтов. |
stream id | 3byte | Указывает идентификатор потока сообщений, формат с обратным порядком байтов. |
Идентификаторы сообщений 1–7 используются для сообщений управления протоколом.
Сообщения 8 и 9 используются для передачи аудио- и видеоданных соответственно.
Сообщения 15-20 используются для отправки команд в кодировке AMF, отвечающих за взаимодействие пользователя и сервера, таких как воспроизведение, пауза.
Реальные данные, содержащиеся в сообщениях в нагрузке. Например, это могут быть аудиосэмплы или сжатые видеоданные.
Сообщение — это базовая единица данных протокола rtmp.,во время передачи по сети,Сообщения переупаковываются в фрагменты для передачи.,Каждый блок имеет фиксированный размер.,Если размер сообщения больше размера блока,Сообщение будет разделено на несколько частей и отправлено.
Блоки состоят из головок инагрузка
ценить | длина | значение |
---|---|---|
basic header | 1 байт или 2 байта или 3 байта | блокировать базовый заголовок |
chunk msg header | 11 байт или 2 байта или 3 байта | кусокзаголовок сообщения |
extended timestamp | 4byte | расширенная временная метка |
ценить | длина | значение |
---|---|---|
fmt | 2bit | формат блока |
cs id | 6bit | Идентификатор блокировки потока |
ценить | значение |
---|---|
0 | выражатькусокзаголовок сообщенияда Тип 0 |
1 | выражатькусокзаголовок сообщенияда Тип 1 |
2 | выражатькусокзаголовок сообщенияда Тип 2 |
3 | выражатькусокзаголовок сообщенияда Тип 3 |
ценить | значение |
---|---|
0 | блокировать базовый заголовок 2 байта, Идентификатор метода расчета блокировки потока (2-й байт + 64),Диапазон(64-319) |
1 | блокировать базовый заголовок 3 байта, Идентификатор метода расчета блокировки потока (3-й байт*255+2-й байт+64),Диапазон(3-65599) |
2 | блокировать базовый заголовок1 байт, 2 представляет сообщение протокола низкого уровня |
3-64 | блокировать базовый заголовок1 байт, это число представляет собой Идентификатор блокировки поток,диапазон(3-64) |
Этот протокол поддерживает 65597 потоков с идентификаторами от 3 до 65599. Идентификаторы 0, 1 и 2 зарезервированы.
Тип 0 имеет общую длину 11 байт и имеет следующий формат:
ценить | длина | значение |
---|---|---|
timestamp | 3byte | Временная метка |
message length | 3byte | нагрузкаиздлина |
message type id | 1byte | идентификатор типа сообщения |
message stream id | 4byte | идентификатор потока сообщений |
Тип 1 имеет общую длину 7 байт и имеет следующий формат:
ценить | длина | значение |
---|---|---|
timestamp | 3byte | Временная метка |
message length | 3byte | нагрузкаиздлина |
message type id | 1byte | идентификатор типа сообщения |
Тип 1 имеет общую длину 3 байта и имеет следующий формат:
ценить | длина | значение |
---|---|---|
timestamp | 3byte | Временная метка |
Тип Блок из 3 не имеет заголовка. Идентификатор потока, длина сообщения, Ни Временная, ни метка не появились. Этот тип блока использует те же данные, что и предыдущий блок. Когда сообщение разделено на несколько частей,Кроме первой части,Все блоки должны использовать этот тип.
расширенная временная метка всего 4 байта, только если заголовок блока сообщения中из普通Временная Это поле передается только в том случае, если для метки установлено значение 0x00ffffff. Если обычный Временная Цена метки меньше 0x00ffffff, тогда это поле не должно появляться.
Формат данных rtmp был подробно объяснен выше. Давайте объясним конкретное содержание протокола rtmp.
Нагрузка блока — это нагрузка на содержимое сообщения.
Подводя итог: сообщение является базовой единицей данных rtmp, а блок используется для повторной инкапсуляции сообщения для передачи по сети.
Типы сообщений RTMP можно разделить на три категории: сообщения управления протоколом, сообщения управления пользователем и командные сообщения RTMP.
Устанавливает размер блока, используемый для уведомления узла о новом максимальном размере блока. Максимальный размер блока по умолчанию составляет 128 байт. Клиенты и серверы могут использовать это сообщение для изменения размера блока по умолчанию. Например, предположим, что клиент хочет отправить аудиоданные размером 131 байт, а размер фрагмента — 128 байт. В этом случае клиент может сообщить серверу, что размер нового фрагмента составляет 131 байт, а затем полные аудиоданные можно отправить одним фрагментом.
Максимальный размер блока рекомендуется составлять не менее 128 байт, но должен быть не менее 1 байта. Каждое направление связи (например, от клиента к серверу) имеет независимые настройки размера блока. Максимальный размер блока поддерживается взаимодействующими сторонами (сервером или клиентом).
Сообщение об установке размера блока занимает всего 4 байта, Формат следующего:
ценить | длина | значение |
---|---|---|
0 | 1bit | Первый бит должен быть 0 |
chunk size | 31bit | Новый максимальный размер блокаценить |
Завершить сообщение,Используется для уведомления узла,Если вы ожидаете частичную часть сообщения (часть сообщения уже получена),那么可以丢弃之前已经接收到изкусок。对端将接收到из Идентификатор блокировки поток в качестве полезной нагрузки текущего управляющего сообщения протокола. Приложение может отправить это сообщение во время завершения работы, чтобы указать, что дальнейшая обработка сообщения не требуется.
Завершить сообщениенагрузка имеет общий размер 4 байта,Формат следующий:
ценить | длина | значение |
---|---|---|
chunk stream id | 4byte | Идентификатор потока блокировки, сообщения этого потока блокировки не будут потеряны полностью |
Клиент или сервер ДОЛЖНЫ отправить сообщение подтверждения партнеру после получения байтов, равных размеру окна. Размер окна относится к максимальному количеству байтов, которое отправитель может отправить до получения сообщения подтверждения от получателя. Это сообщение определяет порядковый номер, который представляет собой количество полученных на данный момент байтов.
Подтверждающее сообщение имеет общий размер 4 байта. Формат следующего:
ценить | длина | значение |
---|---|---|
sequence number | 4byte | Количество полученных на данный момент байтов |
Клиент или сервер отправляет это сообщение, чтобы уведомить другую сторону о размере окна для отправки сообщения с подтверждением (спасибо). Например, сервер хочет получать подтверждение (подтверждение) от клиента каждый раз, когда количество отправленных байтов становится равным размеру окна. Сервер обновляет размер окна для клиента после успешной обработки запроса на соединение клиента.
Размер окна подтверждения составляет всего 4 байта, Формат следующего:
ценить | длина | значение |
---|---|---|
acknowledge window size | 4byte | Подтвердите размер окна |
Клиент или сервер отправляет это сообщение для обновления выходной пропускной способности узла. Цена выходной полосы пропускания такая же, как и размер окна. Если цена, полученная узлом в этом сообщении, не совпадает с размером окна, обратно отправляется сообщение о размере окна подтверждения (подтверждения).
ценить | длина | значение |
---|---|---|
acknowledge window size | 4byte | Подтвердите размер окна |
limit type | 1byte | Поле типа лимита |
Отправитель может типа лимитаотметить сообщение как сложное(0),мягкий(1),Или динамический (2). Если существует жесткое ограничение, партнер должен отправлять данные в соответствии с предоставленной полосой пропускания. Если это мягкий предел,Пиры могут гибко выбирать пропускную способность,Отправитель может ограничить пропускную способность. Если это динамический предел,Пропускная способность может быть жесткой или мягкой.
RTMP использует идентификатор типа сообщения 4 обозначает сообщение управления пользователем. Эти сообщения содержат информацию, используемую уровнем потоковой передачи RTMP. Идентификатор, используемый сообщением управления протоколом: 1、2、3、5 и 6 (Уже представлено ранее). Сообщения управления пользователями должны использовать идентификатор потока сообщений. 0 (который считается потоком управления) и Идентификатор при отправке в виде потока фрагментов RTMP. блокировки поток равен 2. Прием сообщения управления протоколом вступает в силу немедленно при разборе, Временная; Поле метка игнорируется.
Клиент или сервер отправляет это сообщение, чтобы уведомить одноранговый узел о некоторых событиях пользовательского управления.
Эта новость несет в себетип событияиданные о событии,Формат следующий:
ценить | длина | значение |
---|---|---|
event type | 2byte | тип события |
event data | ? | данные о событии |
событие | описывать |
---|---|
Stream Begin (=0) | Сервер отправляет это событие, чтобы уведомить клиента о том, что поток готов и может использоваться для связи. По умолчанию,Это событие отправляется с идентификатором = 0 после успешного получения команды подключения клиента. данные о событии - 4 байта,Представляет идентификатор готового потока. |
Stream EOF (=1) | Сервер отправляет это событие, чтобы уведомить клиента о том, что воспроизведение данных для запрошенного потока закончилось. Перед отправкой дополнительных команд данные больше не отправляются. Клиент будет отбрасывать сообщения, полученные для этого потока. данные о событии имеет размер 4 байта и представляет поток, который воспроизводит завершившийся поток. ID。 |
StreamDry (=2) | Сервер отправляет это событие, чтобы уведомить клиента об отсутствии данных в текущем потоке. Если сервер не обнаруживает никаких сообщений в течение определенного периода времени, он может уведомить соответствующий клиент о том, что в текущем потоке закончились данные. Эти данные о событии — это 4 байта, представляющие поток, в котором нет данных. ID。 |
SetBuffer Length (=3) | Клиент отправляет это событие, чтобы уведомить сервер о размере буфера. (в миллисекундах) этот буфер используется для кэширования любых данных, поступающих из потока. Это событие отправляется до того, как сервер начнет обработку потока. данные о Первые 4 байта событии представляют собой идентификатор потока, а следующие 4 байта представляют длину буфера в миллисекундах. |
Streams Recorded (=4) | Сервер отправляет это событие, чтобы уведомить клиента о том, что текущий поток является потоком записи. данные о событии - 4 байта, представляющие собой поток потока записи ID。 |
PingRequest (=6) | Сервер отправляет это событие, чтобы проверить, доступен ли клиент. данные о событии — это 4-байтовая Временная метка представляет собой местное время сервера, когда сервер отправляет эту команду. После получения этого сообщения клиент немедленно отправит PingResponse отвечать. |
PingResponse(=7) | Клиент отправляет это событие в ответ на PingRequest сервера. данные о событии — это 4-байтовая Временная метка,Должен Временная метка — данные, полученные из PingRequest о Получено от события. |
Клиент или сервер отправляет метаданные и пользовательские данные другой стороне через это сообщение. Метаданные включают дату создания данных.、продолжительность、Тема и другие детали。Тип сообщения18из用AMF0кодирование,Тип сообщения 15 кодируется с помощью AMF3.
Общие объекты распределены по нескольким клиентам,Синхронизированный экземпляр объекта FLASH (набор пар имен). Тип сообщения kMsgContainer=19 закодирован с помощью AMF0.,kMsgContainerEx=16, закодированный с помощью AMF3,Эти два сообщения предназначены для событий общих объектов. Каждое сообщение может содержать несколько событий.
Формат следующий:
событие | описывать |
---|---|
Use (=1) | Клиент отправляет это событие, чтобы уведомить сервер о создании именованного общего объекта. |
Release (=2) | Когда клиент удаляет общий объект,Отправьте это уведомление о событии на сервер. |
Requeset change (=3) | Когда делается запрос на изменение связанной цены именованного параметра общего объекта.,Клиент отправляет это сообщение. |
Change (=4) | При изменении ассоциации именованного параметра,Сервер отправляет это событие всем клиентам. |
Success (=5) | После принятия запроса на изменение события,Сервер отвечает этим сообщением запрашивающему клиенту. |
SendMessage (=6) | Клиент отправляет широковещательное сообщение об этом событии на сервер. После получения этого события сервер рассылает сообщение всем клиентам, включая того, который отправил это событие. |
Status (=7) | для состояния ошибки,Сервер отправляет это событие клиенту. |
Clear (=8) | Сервер отправляет это событие клиенту,Очистить общий объект. Это событие также используется в качестве ответа, когда клиент отправляет usesoeventh при подключении. |
Remove (=9 ) | Сервер отправляет это событие, чтобы клиент удалил слот. |
Request Remove (=10) | Клиент отправляет это событие на сервер при удалении слота. |
Use Success(=11) | Когда соединение успешно Сервер отправляет это событие клиенту. |
Клиент и сервер используют это сообщение для отправки аудиоданных партнеру.
Клиент и сервер используют это сообщение для отправки видеоданных партнеру.
Совокупное сообщение — это отдельное сообщение, содержащее ряд подсообщений.
Формат следующий:
Идентификатор потока сообщений совокупного сообщения переопределит идентификатор потока дочерних сообщений в агрегате сообщений. Совокупное сообщение и первое подсообщение Временная Разница в метке — это смещение, которое используется для добавления Временной к подсообщению. метка Перенормировка на график потока. Смещение добавляется к Временной каждому подсообщению. метка для достижения нормированного времени истечения. Временная для первого подсообщения метка должна сочетаться с Временной метка та же самая, поэтому смещение должно быть ноль. Возвращенный указатель содержит размер предыдущего сообщения, включая его заголовок. сообщения。 Включатьзаголовок сообщения должны соответствовать формату FLV-файла и для обратного поиска.
Командные сообщения передают команды в кодировке AMF между клиентом и сервером. Тип сообщения 20 кодируется AMF0, а тип сообщения 17 кодируется AMF3.
Эти сообщения используются для установления соединения на удаленном конце.,создать поток,выпускать,играи Пауза и другие операции. состояние,Командные сообщения, такие как результаты, используются для информирования отправителя о состоянии запрошенной команды. Командное сообщение состоит из имени команды,Идентификатор транспорта,Состоит из командных объектов, содержащих соответствующие параметры. Клиент или сервер могут использовать командные сообщения для запроса вызовов удаленных процедур с удаленного конца.
В этой части будет представлен процесс передачи rtmp и использование Wireshark для захвата пакетов и анализа примеров.
(1) Подтверждение начинается с отправки клиентом блоков C0, C1.
(2) Сервер отправляет блоки S0 и S1 после получения C0.
(3) После того, как клиент получает блоки S0 и S1, он отправляет блок C2, а сервер отправляет блок S2 после получения блоков C0 и C1.
(4) Когда клиент получает S2, а сервер получает C2, рукопожатие считается успешным после проверки соответственно.
Принципиальная схема выглядит следующим образом:
C0 и S0 имеют только 1 байт, Формат следующего:
ценить | длина | значение |
---|---|---|
version | 1byte | номер версии |
C1, S1 содержит 1526 байт, формат следующий:
ценить | длина | значение |
---|---|---|
time | 4byte | Временная метка |
zero | 4byte | ноль |
random bytes | 1528byte | Это поле используется для проверки |
C2иS2из Формат сообщения
Детали сообщения C2 и S2 такие же, как у C1 и S2.,C2 является копией S1,S2 является копией C1.
Получив C2, сервер сравнит его с S1.
Получив S2, клиент сравнит его с C1.
rtmp использует этот метод, чтобы определить успешность рукопожатия.
(1) Рукопожатие начинается с отправки клиентом блоков C0, C1:
03: Этот байт — C0, что означает номер. версии。
Следующие 1536 байт — это C1.
ff fd fe b4:Временная метка
00 00 00 00: Четыре ноль
Следующие 1528 байт — это случайные числа.
(2) Сервер отправляет блоки S0 и S1 после получения C0:
03: Этот байт — S0, что означает номер. версии。
Следующие 1536 байт — это S1.
ff fd fe b4:Временная метка
00 00 00 00: Четыре ноль
Следующие 1528 байт — это случайные числа.
(3) После того, как клиент получает блоки S0 и S1, он отправляет блок C2, а сервер отправляет блок S2 после получения блоков C0 и C1.
На рисунке ниже показан S2, отправленный сервером:
Как видно, данные те же, что и C1.
На рисунке ниже показан C2, отправленный клиентом:
Как видно, данные такие же, как S1.
Рукопожатие завершено.
(1) Клиент отправляет «сообщение о подключении» для запроса соединения.
(2) После получения запроса на подключение служба отправляет «сообщение подтверждения размера окна».
(3) Сервер отправляет клиенту «сообщение об установке пропускной способности».
(4) После того, как клиент обрабатывает «Сообщение об установке пропускной способности», он отправляет на сервер «Сообщение о подтверждении размера окна» (это сообщение будет отправлено только в том случае, если цена сообщения об установке пропускной способности отличается от размера окна).
(5) Сервер отправляет клиенту сообщение «Начало потока» в сообщении пользовательского управления.
(6) Сервер отправляет «результат» (_result) в «командном сообщении», чтобы уведомить клиента о состоянии соединения.
Принципиальная схема выглядит следующим образом:
«Команда подключения», при которой клиент отправляет командное сообщение на сервер:
03: бит[7:8] означает, что fmt равен 0, бит[0:6] означает идентификатор блокировки поток равен 3 (если он равен 0, это означает, что существует один байт расширения; если он равен 1, это означает, что есть два байта расширения, если он равен 2, это означает базовое сообщение управления протоколом и команду)
Поскольку fmt равен 0, заголовок следующего блока сообщение имеет 11 байт
00 00 00:timestamp
00 00 5f:message length
14:message тип, десятичное число равно 20, что указывает на то, что тип данных сообщения использует кодировку AMF0.
00 00 00 00:msg stream id
Далее идут данные блока
02:amf тип (представляющий строку)
00 07:string длина (представляющая длину строки)
63 6f 6e 6e 65 63 74:string("connect")
00 :amf тип (представляющий двойной тип)
3f f0 00 00 00 00 00 00:val
03:amf тип (представляющий тип объекта)
key:
00 03:string длина (представляющая длину строки)
61 70 70:string("app")
value:
02:amf тип (представляющий строку)
00 04:string длина (представляющая длину строки)
74 79 70 65:string("live")
key:
00 04:string длина (представляющая длину строки)
74 79 70 65:string("type")
val:
02:amf тип (представляющий строку)
00 0a:string длина (представляющая длину строки)
6e 6f 6e 70 72 69 76 61 74 65:string("nonprivate")
key:
00 05:string длина (представляющая длину строки)
74 63 55 72 6c:string("tcUrl")
val:
02:amf тип (представляющий строку)
00 1f:string длина (представляющая длину строки)
72 74 6d 70 3a 2f 2f 31 39 32 2e 31 36 38 2e 31 36 38 2e 31 36 2e 31 32 38 3a 38 30 30 31 2d 6c 69 76 65:string("rtmp://192.168.16.128:8001/live")
00 00 09: Обозначает конец
Сервер отправляет клиенту окно подтверждения:
02: бит[7:8] означает, что fmt равен 0, бит[0:6] означает идентификатор блокировки поток равен 2 (2 представляет базовое сообщение управления протоколом и команду)
Поскольку fmt равен 0, заголовок следующего блока сообщение имеет 11 байт
00 00 00:timestamp
00 00 54:message length
05:message тип (5 указывает на определение размера окна события)
00 00 00 00:msg stream id
00 4c 4b 40:window size
После этого сервер отправил клиенту еще три сообщения.,В документации здесь говорится немного другое.,я тоже не совсем понимаю,Надеюсь, кто-нибудь сможет это объяснить:
Этот поток блоков содержит несколько сообщений
02: бит[7:8] означает, что fmt равен 0, бит[0:6] означает идентификатор блокировки поток равен 2 (2 представляет базовое сообщение управления протоколом и команду)
Поскольку fmt равен 0, заголовок следующего блока сообщение имеет 11 байт
00 00 00:timestamp
00 00 05:message length
06:message тип (6 означает настройку сообщения о пропускной способности однорангового узла)
00 00 00 00:msg stream id
00 4c 4b 40:window размер (пропускная способность 5M)
02 :limit type
0 - Жесткий: партнер должен ограничить свою выходную полосу пропускания не более чем указанным размером окна.
1 - Мягкий: партнер должен ограничить свою выходную полосу пропускания не более чем указанным размером окна или, если ограничение уже существует, выбрать меньшую цену между двумя размерами окна.
2 - Динамический: если предыдущий тип лимита был Hard,Тогда это сообщение также считается жестким сообщением.,В противном случае игнорируйте это сообщение.
02: бит[7:8] означает, что fmt равен 0, бит[0:6] означает идентификатор блокировки поток равен 2 (2 представляет базовое сообщение управления протоколом и команду)
Поскольку fmt равен 0, заголовок следующего блока сообщение имеет 11 байт
00 00 00:timestamp
00 00 04:message length
01:message тип (1 означает сообщение об установке размера блока)
00 00 00 00:msg stream id
00 00 10 00
03: бит[6:7] означает, что fmt равен 0, бит[0:5] означает идентификатор блокировки потокадля1(3выражать Идентификатор блокировки потока)
Поскольку fmt равен 0, заголовок следующего блока сообщение имеет 11 байт
00 00 00:timestamp
00 00 be:message length
14:message тип (20 в десятичном формате, что указывает на то, что данные сообщения закодированы в формате AMF0)
00 00 00 00:msg stream id
02:amf тип (представляющий строку)
00 07:string длина (представляющая длину строки)
5f 71 65 73 75 6c 74:string("_resulte")
00:amf тип (имеется в виду двойной)
3f f0 00 00 00 00 00 00: вал (двойной тип)
03:amf тип (представляющий тип объекта)
key:
00 06:string длина (представляющая длину строки)
66 6d 73 56 65 72:string("fmsVer")
val:
02:amf тип (представляющий строку)
00 0d:string длина (представляющая длину строки)
46 4d 53 2f 33 2c 30 2c 30 2c 31 2c 31 32 33:string("FMS/2,0,1,123")
...
00 00 09:end
(1) Клиент отправляет на сервер «Команду создания потока (createStream)» в «Командном сообщении».
(2) После получения сообщения сервер отправляет «результат (_result)» в «командном сообщении».
Принципиальная схема выглядит следующим образом:
(1) Клиент отправляет «команду createStream» в «командном сообщении» на сервер:
(2) Сервер отправляет «результат (_result)» в «командном сообщении» клиенту:
(1) Клиент отправляет «команду публикации» в «командном сообщении».
(2) После получения сообщения сервер отправляет «streambegin» в сообщении управления пользователем.
(3) Клиент начинает отправлять аудио- и видеоданные.
Принципиальная схема выглядит следующим образом:
Клиент отправляет «команду публикации» в «командном сообщении»:
Ответ сервера:
Клиент отправляет мультимедийную информацию:
…
Клиент отправляет мультимедийные данные:
…
Заявление об авторских правах: Содержание этой статьи добровольно предоставлено пользователями Интернета, а мнения, выраженные в этой статье, представляют собой только точку зрения автора. Данный сайт лишь предоставляет услуги по хранению информации, не имеет никаких прав собственности и не несет соответствующей юридической ответственности. Если вы обнаружите на этом сайте какое-либо подозрительное нарушение авторских прав/незаконный контент, отправьте электронное письмо, чтобы сообщить. После проверки этот сайт будет немедленно удален.
Издатель: Лидер стека программистов полного стека, укажите источник для перепечатки: https://javaforall.cn/200812.html Исходная ссылка: https://javaforall.cn