流媒体学习3

发布时间 2023-12-08 14:17:32作者: 泽良_小涛

2)详探

 应用程序app

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTGJzWnEwcHJhdHN2cXRpYXkxZWJueDgwNTNRczZLbExhb1JuMHNmRVZaT0R1YXZPeUREU2NzbVEvNjQw?x-oss-process=image/format,png

app是application的缩写,代表客户端要链接到的,rtmp服务器的应用程序,这个一般我们在nginx服务器的配置选项中可以看到。对于该object,首先使用app来表示此object表示的名称,之后按照AMF0格式来表示具体的值。此处app的值为rtmp_live,是字符串类型,占用9个字节。正好,此次请求的rtmp的应用程序确实是rtmp_live,可参照rtmp配置文件。

版本flashVer

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTGN2N29JaWNpYXJ5QnpxMDV2SUVrR1ZmaWFXQVAwR0diV3ZIUjNZVTJmNkFXMU54Y0hibGlicm5QZ0EvNjQw?x-oss-process=image/format,png

flashVer表示flash播放器的版本号,同样首先通过一个字符串来表示object的类型;然后再用AMF0的编码格式对具体的值进行编码,此处是flash的版本号,采用字符串表示,值为"LNX 9,0,124,2"。

链接tcUrl

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTGMwYnpVclVxQ0NrNEJteHJCcTVJaFduSG50UmliN29zdWozQTk3Z09ZREE3RXd6M2liNGdmcERBLzY0MA?x-oss-process=image/format,png

服务器的URL地址,其格式为

protocol://servername:port/appName/appInstance

比如例子中服务器的url地址为

rtmp://192.17.1.200:1935/rtmp_live(此处省略了appInstance)

看抓包文件,我们可以看出,对于tcUrl字段的object,同样是先用一个字符串来表示类型,其后以AMF0的编码格式对具体的数值进行编码(此处还是字符串形式)。

代理标志fpad

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTFJWMGs4TXl4eVFtYjNHT1BMaWFuS0ZEOHpEUTlEcVEwakN0bkRwZnZsT2NtaWFFQWpVbmNSQ2F3LzY0MA?x-oss-process=image/format,png

fpad是一个布尔值,用来表示是否使用代理。如果使用,值为true,否则值为false。抓包文件中还是首先用一个字符串表示Object的类型,然后按AMF0的格式进行编码。此处为Bool类型,所以比较简单,0x01表示布尔类型,Bool类型没有长度字段,占用一个字节,其后使用一个字节来表示true或者false,此处为false。

能力capabilities

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTFNKWFllY2ZobjU5b0ViaWM2MUZnSzhVbWdTWWliSEdzY1BHd0pQQUxERlh6Nk9tUGV3cHdQS2ljdy82NDA?x-oss-process=image/format,png同样,先用字符串表示object的类型,然后再用跟着具体的值,此处为一个数值类型,值为15,即capabilities的值为15。

音频audioCodecs

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTHdqVzM1cmVpYXl6bUV4THNxaFpGcEtzelZpYnJ4eU9TWUNSMkdxYmZwZWJqWnZtS3Y4NnBmQnlBLzY0MA?x-oss-process=image/format,png

audioCodes表示支持的音频编码格式,支持的每一种格式用一个bit位来表示,所有的比特位进行或运算得到最终的值。以本抓包文件为例,codecs的值为4071,4071对应的二进制为 0000 1111 1110 0111。

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTHJmbXZTQ1l3bmRnUkw5Zm0wU3FrZ0hJM2hrRlhpYmdTUGNvRjY1YmFpYWZNN3pWTEFGb050QllBLzY0MA?x-oss-process=image/format,png

然后我们再看下不同的bit位对应的codec编码器,如下图:

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTDZ0dFhpY0ZhQ1lVUms3aWNLNGt2SjREaWJVbnRZdzlmRVFKaWFwMXlGS0NCR0dYazRwTzVpYWhxUVV3LzY0MA?x-oss-process=image/format,png

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTFNPN3JVVnpZVVlkUjN1RnN3ZmNpYzhETWVxNmRzNFF1Vmlid2RSaWNDeUZMTlliWnVQY25ManBUQS82NDA?x-oss-process=image/format,png

对照表,我们可以得出本次连接支持哪些格式的音频编码。简单举个例子,4071中包含0x0400,表明此次rtmp请求音频是支持AAC的,其他标志类似。

视频videoCodecs

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTFNpYklQZW5WMzVudDZrOVNDc1BIWG5tczFJaFRUQWNXZ3hKemliMUc5M2xpYW1IVVBPZkhkOW8zQS82NDA?x-oss-process=image/format,png

说完audioCodecs,再说videoCodecs就简单多了,同样的逻辑,同样的codec表示方式 。此抓包文件中videoCodec的值为252,对应的二进制表示为:

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTHNTY25XVURXTUUydGlhRlgzVnlic20zcFdBMzFaa1A0VlpGOXdpYmlhVUZQRWNpYmliTzdzdGNYaDlRLzY0MA?x-oss-process=image/format,png

252 = 0x0040 | 0x0080 | 0x0010 | 0x0020 | 0x0040 | 0x0080

再对照videoCodecs的定义

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTDRlam80UFJKa0lxczhHbDdqdUpwU1VlQjdKaWN0dGZCZ21uOEhic3RycWljQ2NOcE4ya3NGVEJRLzY0MA?x-oss-process=image/format,png

以0x0080为例,我们得知此次rtmp连接针对视频支持H264编码。

帧搜索videoFunction

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTGlhMFhLbmt2YUJBemhNaWNFTDlpYWZlR2dNeUI0eDUwYUJJVTBDZ2RKYUhnVlJOU0p0d2haQVY5QS82NDA?x-oss-process=image/format,png

videoFunction也比较简单,先用字符串表明类型,然后紧跟着一个number类型的数据,值为1。videoFunction的值为1,表示客户端可以执行精确到帧的搜索。

3)connect消息流

客户端和服务端通过connect进行交互的一些流程:

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTG1CNkQ3MlJPbjNLaWJqTGFpYzdoa09hZ0J2RGVLMjdTMHFsYXZmbEdaMkJoRDh0UlByS0pTUnN3LzY0MA?x-oss-process=image/format,png

  • 客户端发送connect命令到服务器,请求与服务端的application进行连接;
  • 服务端收到connect命令后,服务器会发送协议消息“Window Acknowledgement size”消息到客户端。服务端同时连接到connect中请求的application;
  • 服务端发送协议消息“Set Peer BandWidth”到客户端;
  • 客户端在处理完服务端发来的“Set Peer BandWidth”消息后,向服务端发送“Window Acknowledgment”消息;
  • 服务端向客户端发送一条用户控制消息(Stream Begin);
  • 如果连接成功,服务端向客户端发送_result消息,否则发送_error消息。

至此,关于connect的消息暂时到这,接下来我们分别看看“Window Acknowledgement Size”、“Set Peer BandWidtth”以及_result消息。

5.result消息

rtmp客户端发送connect消息之后,rtmp server会给客户端发送_result消息,通过该消息通知客户端连接状态(success/fail)。

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTEtscGlieW5VNkdNTEZUTHlkZ0VnUHhOTWlhZGUwWHBkUWF2aDZzQXYzQkV5WUt1YW01bWpHUmx3LzY0MA?x-oss-process=image/format,png

1)概览

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTGVKd0JpYkRybnVORkcwOTVRNGxDOXJaVlYxTGpVMWdSSEk5TVJQNTFMZk1RdW5wOFVRZTF6REEvNjQw?x-oss-process=image/format,png

一个_result消息由4部分组成,类型标识,transaction ID,properties,response related information,这四部分均以AMF格式进行编码。

2)详解

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTEp4eWxOUEYzMGliSFpLWUt1NXB3M3JoUENwRVpBNXFzd0VpYzlsdGxjU2xCbzR4NzRCYlRtSUlRLzY0MA?x-oss-process=image/format,png

典型的类型+长度+值的AMF组合,不多说了,_result表示消息类型。

transaction ID

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTDF0Qk9uQUZhSUFneXJJOG1lUUxpYW5WbmpyNDZ3b2xpY2tScGJYSmZYNWdpY3gwMjhsMWFEVE5NQS82NDA?x-oss-process=image/format,png

transcationID,按照AMF0格式编码,0x00表示数字格式,其后用8个字节表示ID,对于connect消息的回复,此ID恒为1。

properties

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTDFQTGN6WDFpY3FaaWMxNVIxclBlYXpvc29uNUJQdUVndlZRQWlhNXVSRlpaaDdRZXJRd3VSM3dpYkEvNjQw?x-oss-process=image/format,png

可以看出properties中包含了两个Object类型的数据,一个fmsVer表示了FMS 服务器的版本信息(此处为FMS/3,0,1,123),另外一个capabilites表示容量,值为31。关于RTMP Body中的Object对象数据组织格式,就不赘述了,可以参照之前对于connect消息的详细解释。

response related information

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTFJwaWNrR0VFaDg1M2V5VGFTWTJoUlNOZGliTjlDbzlncHo0N09EUmdhbHNZMkUzU2Q0OXNGVHl3LzY0MA?x-oss-process=image/format,png

通过看抓包文件,我们可以看出这里包含许多关于connect连接的响应,以object类型进行组织。有level,此处为status,意味表示连接的状态;code,表示代码,可以理解为某种编号,此处为NetConnection.Connect.Succes;description可以理解为对code的描述,此处为‘Connection succeeded’。code与description联合起来,表示此次连接成功;还有关于objectEncoding字段,表示object以那种方式编码(AMF0或者AMF3),此处值为0,表示采用AMF0编码。

客户端收到_result,获取连接状态为Connection succeeded。这样关于连接的建立基本就完成了,接下来就可以进行流相关的操作了。

6.connect后续三剑客

connect消息的时候,我们说过服务器收到connect消息之后,会向客户端发送Window Acknowledgement Size消息和Set Peer Bandwidth消息。

1)概览

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTGJwVEpKOVRqbVlBb21pYlBiTTNDN0k2Y0p5ZkpEb2lhS2poUnlxSjlodW9TU09wRHNpYno4anIwZy82NDA?x-oss-process=image/format,png

示例中服务器ip地址是192.17.1.200,客户端ip地址是192.17.1.92,客户端向服务器发送connect消息之后,服务器向客户端发送了Window Acknowledgement Size和Set Peer Bandwidth消息。

2)Window Acknowledgement  Size消息

Window Acknowledgement Size用来通知对端,如果收到该大小字节的数据,需要回复一个Acknowledgement消息,也就是ACK。本例中,设置的大小为500000,也就是服务端通知客户端如果收到了50000字节的数据,需要向服务端发送一个ACK的消息,而实际上一般情况一个会话中能达到如此大的数据量比较少,所以我们也看到会回复ACK消息的消息比较少,更多的只是看到设置接收窗口大小的消息(Window Acknowledgement Size),接下来我们看一下抓包。

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTDliTURtRWxLaWE0M2ZaTktraWJpYkR6dVZpY1NrVGliNUdsbTdNaWFESUJIQnBpYW11eExxbHkxSzJEMEEvNjQw?x-oss-process=image/format,png

消息格式比较简单,组织结构是RTMP Header + RTMP Body,Header的结构就不赘述了,参考前面的文章;Body中直接使用4个字节表示要设置的大小,此处为0x004c4b40=5000000。

3)Acknowlegement消息

Acknowlegement消息可以理解为Window Acknowlegement Size满足条件的触发消息,当一端收到的数据大小满足Window Acknowledgement Size设置的大小时,向对端发送Ack消息。

Acknowlegement消息,也按照RTMP Header + RTMP Body进行组织,其Body也直接使用4个字节,表示收到数据满足Window Acknowledgement Size的最后一个数据包的序列号。我们来看一个抓包文件:

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTHV5Nm9jdEhVUDNyaWI2UXppYnBWOEhhNmljWmEyWjJZZUZ4YmRwUjhxakNvbjN0TFZzdGtqMmpxZy82NDA?x-oss-process=image/format,png

该条消息表示,在序列号为2507670的时候,rtmp客户端已累计收到5000000个字节的数据,此时向服务端发送一个ACK。

另外我们也验证一下,交互过程中,更多的看到Window Acknowledgement Size消息,而很少看到Acknowlegement消息。

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTHhtZmFLdWpBRWliSEVmNklWNmljQnY4dlRNVDE5Qm04WWNlb2dBMll0aEhlWmliU3dlNTRwbTdYQS82NDA?x-oss-process=image/format,png

说明:wireshark中可以针对rtmp消息进行过滤

过滤Window Acknowledgement Size

rtmpt.header.typeid == 0x05

过滤Acknowledgement 

rtmpt.header.typeid == 0x03

照猫画虎,可以对照下表进行过滤:

更多的关于wireshark抓包关于rtmp的过滤条件,参照:

https://www.wireshark.org/docs/dfref/r/rtmpt.html

4)Set Peer BandWidth消息

该消息里设置对端输出带宽,对端是通过设置Window Acknowledgement Size来实现流量控制的。超过Window Acknowledgement Size后未确认(不发送Acknowledgement)发送端将不再发送消息。所以对端收到set peer bandwidth后,如果之前发送的Window Acknowledgement Size和这里写的的Window Acknowledgement Size不一样,一般会发送一个Window Acknowledgement Size。

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTFh0VEFEQ2NGeDdiWmlhcDVpYURmaEtsSmlhamFvYmxnVnpPWWtKNXM3eWJ5Z0hvZXQzdGljZTBtQkEvNjQw?x-oss-process=image/format,png

刚开始建立连接,服务器向客户端发送Set Peer Bandwidth消息,客户端第一次收到Set Peer Bandwidth消息,之前没有发送过Window Acknowledgement Size,所以在这里向服务端发送一次消息。

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9rYVk0SkcxdE9EUW5pYklEZWxwUFVmaWJwV3BuSkxMeGliTE1scHg1SVVUdGljaWFOTmhGaWExQXJUVjZ4QWpUVEl4MWNpYmJIeUtHTVIyS1RTbGxyVWRwQWljMHdnLzY0MA?x-oss-process=image/format,png

Set Peer Bandwidth消息还是按照RTMP Header + RTMP Body的格式组成。RTMP Body由两个字段组成,一个是Window acknowledgement size,占用4个字节;一个是limit type,表示限制的类型,可取的值为0(Hard),1(soft), 2(Dynamic)。本例中采用的是Dynamic。

limity type表示了不同的限制策略:

  • Hard:收到消息的一端需要按照消息中设置的Window size进行限制;
  • Soft:收到消息的一端按照消息中设置的Window size或者已经生效的限制进行限制,以两者中较小的为准。
  • Dynamic:如果之前的类型为Hard,则此消息也为Hard类型,否则忽略该类型。