手撕Rtmp协议细节(6)——connect后续三剑客

 

在讲解connect消息的时候,我们说过服务器收到connect消息之后,会向客户端发送Window Acknowledgement Size消息和Set Peer Bandwidth消息,这一篇就来介绍一下这两条消息。

 

1.概览

首先从抓包文件看一下:

示例中服务器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),接下来我们看一下抓包。

手撕Rtmp协议细节(6)——connect后续三剑客_第1张图片

消息格式比较简单,组织结构是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的最后一个数据包的序列号。我们来看一个抓包文件:

手撕Rtmp协议细节(6)——connect后续三剑客_第2张图片

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

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

手撕Rtmp协议细节(6)——connect后续三剑客_第3张图片

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

过滤Window Acknowledgement Size

rtmpt.header.typeid == 0x05

过滤Acknowledgement 

rtmpt.header.typeid == 0x03

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

typeID

消息类型

说明

0x00

Unkown

 

0x01

Set Chunk Size

设置Chunk大小

0x02

Abort

 

0x03

Window Acknowledgement Size

 

0x04

User Control Message

空户控制消息(如Stream Begin等)

0x05

Acknowledgement

 

0x06

Set Peer Bandwidth

 

更多的关于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。

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

还是看抓包文件:

手撕Rtmp协议细节(6)——connect后续三剑客_第4张图片

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类型,否则忽略该类型。

 

5.StreamBegin

 

手撕Rtmp协议细节(6)——connect后续三剑客_第5张图片

服务端发送Set Peer Bandwidth消息之后,客户端向服务端发送Window Acknowledgement Size消息,服务端再向客户端发送一条用户控制消息StreamBegin。

wireshark中过滤StreamBegin消息的条件如下:

rtmpt.header.typeid == 0x04 and rtmpt.ucm.eventtype == 0x00

StreamBegin属于用户控制类消息,header的typeid为0x04。而用户控制消息的类型的定义如下:

type

消息

说明

0x00

Stream Begin

 

0x01

Stream EOF

 

0x02

Stream Dry

 

0x03

SetBufferLength

 

0x04

StreamIsRecoreded

 

0x06

PingRequest

 

0x07

PringResponse

 

如此,我们就得出了StreamBegin的过滤条件。接下来我们看看StreamBegin消息,还是先看一下抓包文件:

手撕Rtmp协议细节(6)——connect后续三剑客_第6张图片

RTMP服务器发送StreamBegin以通知客户端流已经可以使用并且可以用于通信。默认情况下,从客户端成功接收到connect命令后,将在ID 0上发送StreamBegin。StreamBegin的数据字段占用4字节,其类型占用2个字节,所以RTMP Body部分总共占用6个字节(类型+数据)。其中数据字段代表已开始运行的流的流ID,此例中为1。

好了,这一篇就到这里了,下一篇我们继续手撕Rtmp协议细节,不要走远!

 

扫描二维码获取更多精彩

 

 

你可能感兴趣的:(手撕Rtmp协议)