直播协议RTMP_rtmp推流与拉流

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

说起RTMP协议相信很多人都比较陌生这个协议相对HTTP、HTTPS、TCP等我们常见的协议而言我们在工作中确实较少接触它但是对现在如火如荼的直播行业RTMP是一个重要的协议它在实时音视频场景中使用非常广泛而且目前市占率很高。 本文的主要内容是分析RTMP的协议当然不是纯理论分析这样没多大意思还是结合实践抓包文件来具体分析这样才能较好地理解RTMP的内涵。具体如何抓包见本文末尾的“Android抓包”模块。希望你阅读完本章之后自己也能简单地动手操作一下这样理解深刻一下。

原版的协议内容太冗长了感兴趣可以看一下www.adobe.com/devnet/rtmp…

RTMP基础介绍 RTMP协议的主要特点

  • RTMP协议是应用层协议是要靠底层可靠的传输层TCP

  • 协议通常是TCP来保证信息传输的可靠性的。在基于传输层协议的链接建立完成后RTMP协议也要客户端和服务器通过“握手”来建立基于传输层链接之上的RTMP Connection链接。播放一个RTMP协议的流媒体需要经过以下几个步骤握手建立网络连接建立网络流播放。服务器和客户端之间只能建立一个网络连接但是基于该连接可以创建很多网络流。

这儿埋下一个小疑问为什么传输层已经建立了TCP连接RTMP还需要再次建立一个连接有这个必要吗

RTMP协议传输时会对数据做自己的格式化这种格式的消息我们称之为RTMP Message而实际传输的时候为了更好地实现多路复用、分包和信息的公平性发送端会把Message划分为带有Message ID的Chunk每个Chunk可能是一个单独的Message也可能是Message的一部分在接受端会根据chunk中包含的data的长度message id和message的长度把chunk还原成完整的Message从而实现信息的收发。

RTMP握手

RTMP基于TCP已知TCP需要3次握手才可以建立连接在TCP3次握手成功之后应用层的RTMP也是需要握手的就是认证过程。具体的认证过程如下

  • 客户端发送 C0、C1、 C2服务器发送 S0、 S1、 S2。

  • 首先客户端发送 C0 表示自己的版本号不必等对方的回复然后发送 C1 表示自己的时间戳。

  • 服务器只有在收到 C0 的时候才能返回 S0表明自己的版本号如果版本不匹配可以断开连接。

  • 服务器发送完 S0 后也不用等什么就直接发送自己的时间戳 S1。客户端收到 S1 的时候发一个知道了对方时间戳的 ACK C2。同理服务器收到 C1 的时候发一个知道了对方时间戳的 ACK S2。

  • 握手建立完成。

现在回答上面提出的问题为什么RTMP还需要单独建立一个连接 因为它们需要商量一些事情保证以后的传输能正常进行。主要就是两个事情一个是版本号如果客户端、服务器的版本号不一致则不能工作。另一个就是时间戳视频播放中时间是很重要的后面的数据流互通的时候经常要带上时间戳的差值因而一开始双方就要知道对方的时间戳。 光讲纯理论没意思还是抓包看一下具体的流程吧。 1.首先TCP 3次握手

2.RTMP握手过程

★文末名片可以免费领取音视频开发学习资料内容包括FFmpeg webRTC rtmp hls rtsp ffplay srs以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

我们发现真实发包是C0+C1一起发S0、S1、S2一起发。但是发送的时候还是会严格按照时序来控制的这样才能真正校验好版本号等字段。

拉流

RTMP拉流的核心流程如下

1.建立网络连接

客户端发送命令消息中的“连接”(connect)到服务器请求与一个服务应用实例建立连接。 StreamID是每个消息的唯一标识划分成Chunk和还原Chunk为Message的时候都是根据这个ID来辨识是否是同一个消息的Chunk的这里面为0说明这个消息是初始的0消息。 Chunk stream ID一个RTMP message会拆分成多个chunk同一个Chunk Stream ID必然属于同一个Message。这样在传送过程中发过来的chunk就是通过chunk stream ID最终组装成功我一个完成的message数据的。 message type id(消息的类型id)表示实际发送的数据的类型如8代表音频数据、9代表视频数据。如下面的两张图这样看上去是不是好理解一点了。

type。共有4种不同的格式其中第一种格式字段为0可以表示其他三种表示的所有数据但由于其他三种格式是基于对之前chunk的差量化的表示因此可以更简洁地表示相同的数据实际使用的时候还是应该采用尽量少的字节表示相同意义的数据。因为type 0是表示不同数据其他是差量所以可以想象如果搜不到type 0的包说明这个流肯定有问题。可以通过“rtmpt.header.format == 0”过滤。 2.建立一个网络流 网络流代表了发送多媒体数据的通道。服务器和客户端之间只能建立一个网络连接且多个网络流可以复用这一个网络连接。这个在上面已经反复说过。 客户端向服务器请求创建流

服务器收到请求后向客户端发送_result()对创建流的消息进行响应。此时NetStream创建完成。

3.Play 播放

客户端发送命令消息中的“播放”play命令到服务器。

接收到播放命令后服务器发送设置块大小ChunkSize协议消息。 服务器发送用户控制消息中的“streambegin”告知客户端流ID。

播放命令成功的话服务器发送命令消息中的“响应状态” NetStream.Play.Start告知客户端“播放”命令执行成功。

我们发现执行了3个动作分别如下

共用一个Stream ID并且在可以播放消息回来之后已经解析出视频的基本属性。

推流

分析完拉流的所有操作启示推流也是类似的区别在Play ---> Publishing了。

Android抓包

  • 进入网站www.androidtcpdump.com/android-tcp… tcpdump工具现在最新版本是4.9.3

  • 找一个root的手机将下载好的tcpdump文件先push到/sdcard/ 下面adb push tcpdump /sdcard/tcpdump

  • adb shell进入手机adb 模式下cp -rf /sdcard/tcpdump /data/local/将tcpdump拷贝到/data/local/目录下

  • chmod 777 /data/tcpdump赋予tcpdump完全的执行权限

  • ./data/local/tcpdump -i any -p -s 0 -w /sdcard/capture.pcap

  • 然后开始访问rtmp的请求访问完成后会在/sdcard/目录下生成capture.pcap文件

  • adb pull /sdcard/capture.pcap 本地使用wireshare分析capture.pcap文件

  • rtmp的测试源提供一个rtmp://58.200.131.2:1935/livetv/hunantv

作者安纯旦 

★文末名片可以免费领取音视频开发学习资料内容包括FFmpeg webRTC rtmp hls rtsp ffplay srs以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6