网络传输相关

RTP:实时传输协议,主要用来传输音视频媒体数据用的。

RTP在协议中的位置

RTP存在的价值:

音视频实时传输需要做音视频同步,依靠协议中的时间戳,通过时间戳确定音视频实时播放的时间点。

音视频实时传输,丢包、乱序,重复包都会花屏,重传没有实时效果,所以需要序列号判断丢包、乱序、重复包并做相应处理。

视频帧的传输需要分包后组包,需要依靠时间戳

多个音频源,视频源会话时,需要混音混屏处理,需要依靠同步源标识每一路音频每一路视频。

混音混屏后需要知道mix之后的数据的来源(频道)需要依靠特约信源csrc

同一个音频源或者视频源如果存在多种类型的编码数据需要依靠PT(PayloadType)来区分。

传输的时候如果还需要自定义的其他数据,需要增加扩展头,此时需要依靠X位来说明。

版本号(V):2比特,用来标志使用的RTP版本。
填充位(P):1比特,如果该位置位,则该RTP包的尾部就包含附加的填充字节。
扩展位(X):1比特,如果该位置位的话,RTP固定头部后面就跟有一个扩展头部。
CSRC计数器(CC):4比特,含有固定头部后面跟着的CSRC的数目。
标记位(M):1比特,该位的解释由配置文档(Profile)来承担.
载荷类型(PT):7比特, 表示传输的多媒体类型
序列号(SN):16比特,发送方在每发送完一个RTP包后就将该值增加1,接收方可以由该值确定包的丢失及恢复包序列。序列号的初始值是随机的。
时间戳:32比特,记录了该包中数据的第一个字节的采样时刻。在一次会话开始时,时间戳初始化成一个初始值,时间戳的数值随时间而不断地增加。时间戳是去除抖动和实现同步不可缺少的。同一个帧的不同分片的时间戳是相同的。这样就省去了起始标志和结束标志。一定要记住,不同帧的时间戳肯定是不一样的。
同步源标识符(SSRC):32比特,同步源就是指RTP包流的来源。在同一个RTP会话中不能有两个相同的SSRC值。该标识符是随机选取的 RFC1889推荐了MD5随机算法,是全局唯一的。
特约信源标识符(CSRC List):0~15项,每项32比特,用来标志对一个RTP混合器产生的新包有贡献的所有RTP包的源。由混合器将这些有贡献的SSRC标识符插入表中。SSRC标识符都被列出来,以便接收端能正确指出交谈双方的身份

RTCP:

打包:3种封包类型:单一NALU封包,组合包(多个NALU一个RTP包),分片包(一个NALU分成多个RTP包)。

单一包,直接RTP头加上NALU,type:跟NALU一致,1到23

1个H264 NAU数据 [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ] ,封包后为 [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

组合包:RTP头 + 一个字节的负载头(type,24,,25,26,27)+ 2字节包长度 + payload

STAP-A   单一时间的组合包 F=0 NRI=3 type=24 , 01111000(0x78)
STAP-B   单一时间的组合包  F=0 NRI=3 type=25 , 01111001(0x79)
MTAP16   多个时间的组合包  F=0 NRI=3 type=25 , 01111010(0x7a)
 MTAP24   多个时间的组合包  F=0 NRI=3 type=25 , 01111011(0x7b)

2个H264 NAU数据 [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ] [00 00 00 01 68 42 B0 12 58 6A D4 FF ... ],封包后 [ RTP Header ] [78 (STAP-A头,占用1个字节)] [第一个NALU长度 (占用两个字节)] [ 67 42 A0 1E 23 56 0E 2F ] [第二个NALU长度 (占用两个字节)] [68 42 B0 12 58 6A D4 FF ... ]

分片包: FU(A,B两类,FU_A:28,FU_B:29):RTP包头 + 1字节的FU指示单元+1字节的FU头。指示单元28表示A类,29表示B类,FU头指示分片的起始包,结束包,中间包。

 1个H264 NAU数据  [00 00 00 01 65 42 A0 1E 23 56 0E 2F ...  02 17 C8 FD F1 B9 C7 53 59 72 ... CB FF FF F4 1A D5 C4 18 A8 ... F1 B9 C7 1D A5 FA 13 0B ...],拆包后 为:

[ RTP Header ] [ 7C 85 42 A0 1E 23 56 0E 2F ...]

[ RTP Header ] [ 7C 05 02 17 C8 FD F1 B9 C7 53 59 72 ...]

[ RTP Header ] [ 7C 05 CB FF FF F4 1A D5 C4 18 A8 ...]

[ RTP Header ] [ 7C 45 F1 B9 C7 1D A5 FA 13 0B ...]

如上,在RTP数据序列中如果看到 7c 85 那就是 FU_A 的第开始包,7c 05 中间包,7c 45 结束包。

QoS

QoS的关键指标主要包括:可用性、吞吐量、时延、时延变化(包括抖动和漂移)和丢失

RTP扩展头

RTP包的扩展字段是怎么扩展的?

typedef struct {
unsigned short rtp_extend_profile; /**< profile used*/
unsigned short rtp_extend_length; /**< length, for tang, it is 2 for two 32 bit */
unsigned int rtp_extend_command; /**< package command */
unsigned int rtp_extend_channel; /**< tang channel id, use to idenitify the channel */
} RTPEXTENDHEADER;

typedef union {
struct {
unsigned short DT: 2;
unsigned short E: 2;
unsigned short UIDC: 4;
unsigned short SEQ: 8;
} stv;
short sv;
} PROFILE;

RFC3550:

0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |V=2|P|X|  CC   |M|     PT      |       sequence number         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           timestamp                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           synchronization source (SSRC) identifier            |
   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
   |            contributing source (CSRC) identifiers             |
   |                             ....                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

其中X位如果为1,就表示CSRC后面还有一些额外的RTP扩展头,其形式如下(只支持一个扩展头

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      defined by profile       |           length              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        header extension                       |
   |                             ....                              |
RFC5285(支持多个扩展头):

One-Byte Header

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |       0xBE    |    0xDE       |           length =3           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |  ID   | L=0   |     data      |  ID   |  L=1  |   data...
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
            ...data   |    0 (pad)    |    0 (pad)    |  ID   | L=3   |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          data                                 |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Two-Byte Header

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |       0x10    |    0x00       |           length=3            |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |      ID       |     L=0       |     ID        |     L=1       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |       data    |    0 (pad)    |       ID      |      L=4      |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          data                                 |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

MTU 最大传输单元

在链路层,由以太网的物理特性决定了数据帧的长度为(46+18)-(1500+18),其中的18是数据帧的头和尾,也就是说数据帧的内容最大为1500(不包括帧头和帧尾),即MTU(Maximum Transmission Unit)为1500;

在网络层,因为IP包的首部要占用20字节,所以这的MTU为1500-20=1480;

在传输层,对于UDP包的首部要占用8字节,所以这的MTU为1480-8=1472,所以,在应用层,Data最大长度为1472。

当UDP包中的数据多于MTU(1472)时,发送方的IP层需要分片fragmentation进行传输,而在接收方IP层则需要进行数据报重组,由于UDP是不可靠的传输协议,如果分片丢失导致重组失败,将导致UDP数据包被丢弃。所以尽量UDP的数据小于1472字节避免分片重组。TCP : 1500 - IP头(20) - TCP头(20) = 1460 (Bytes)

在网络编程中,Internet中的路由器可能有设置成不同的值(小于默认值1472),Internet上的标准MTU值为576,所以Internet的UDP编程时数据长度最好在576-20-8=548字节以内。

MTU 是由于链路层特性决定所以IP层不得不分包的,这个对传输层透明,即传输层不存在MTU的限制。在传输层,UDP包大小是受UDP协议要求包小于64K(32位的数据长度字段限制)。TCP没有限定,TCP包头中就没有“包长度”字段。这就是为什么TCP常常被称作一种“流协议”的原因,开发者在使用TCP服务的时候,不必去关心数据包的大小,只需讲SOCKET看作一条数据流的入口,往里面塞数据即可,TCP协议本身会进行拥塞/流量控制。

链路层:

IP

TCP

UDP

滑动窗口

窗口包含在缓存中。接收方的app如果处理不过来会使数据在接收缓存中滞留导致接收窗口变小,从而影响对端发送窗口变小。

接收窗口以seq范围标识可接收的数据范围,落在这个seq范围的数据可以缓存起来,落在这个外面的被扔掉。接收到的数据可能落在窗口边缘可能落在窗口中间,落在窗口中间的需要缓存下来等待左边界的数据完全接收。

发送窗口受接收窗口的影响。发送完的数据要等待得到确认之后才能出窗口,积累着没有得到确认的话会是发送窗口不断变小。

发送的帧超时未得到确认时,需要重传。重传机制受确认机制的影响。累计确认方式需要后退N帧重传。

TCP 头里有一个字段叫 Window,也就是窗口大小。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据,于是发送端就可以根据这个接收端的处理能力来发送数据。

发送窗口

接收窗口

3次握手

目的:传输可靠性验证。C端必须验证S端是否正常接收,S端也要验证C端是否正常接收。第1次发起握手,没有第2次C端就不知道S端是否能正常接收,没有第3次S端就不知道C端是否能正常接收。

C端不正常接收的场景:

1. C端发送连接请求之后挂掉了。这种情况第二次握手失败,如果存在第3次握手,S端会一直等待第3次握手,如果超时收不到第3次握手,S端会重新发送第2次握手。如果设计的时候没有第3次握手,那第2次握手失败S端没法知道,S端就会一直保持连接等待接收数据,永远不释放,造成资源泄漏。

2. C端发送的连接请求过期被作废了。这种情况如果设计有第3次握手,那在C端接收到S端对过期请求的ack之后会发RST告诉S端关闭连接。如果设计没有第3次请求S端就会认为连接成功然后一直保持连接等待永远不会来了的数据,造成资源泄漏。

4次挥手

 

C端第1次主动挥手请求,S端回复收到请求等待结束,S端完成后续事情之后第3次挥手告诉C端可以结束连接,第4次挥手,S端关闭连接,C端延时关闭连接。

第3次挥手表明S端所有数据已经发送完毕,但发送出去的数据不一定都已经有了确认回复,所以S端需要继续等待数据回复和第3次挥手的回复。C端可能在第3次挥手之后还需要再等有可能延迟到的S端数据或者C端的确认回复丢失S端需要重传的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tangcpp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值