转自《RTMP协议详解(一) (二) (三) 》

Real Time Messaging Protocol(实时消息传送协议协议)是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的私有协议。

具体使用RTMP的AS代码大概如下:

  var videoInstance:Video = your_video_instance;

  var nc:NetConnection = new NetConnection();

  var connected:Boolean = nc.connect("rtmp://localhost/myapp");

  var ns:NetStream = new NetStream(nc);

  videoInstance.attachVideo(ns);

ns.play("flvName");

Adobe也在官方网站已经提供了RTMP协议的官方文档说明,为什么要写这个系列文章最大的原因只是对前一段工作的一个总结和回顾,最近两个月,实现了一个RTMP Server的c++版本,把公司的流媒体服务和flash无缝对接起来。希望我的文字能给后来研究这个协议的同学有一定的帮助。

RTMP协议是一个基于TCP的高层协议族,当然这个玩意据说还有UDP协议版本的,不过现在还没有出来,好像Adobe下一版本的FMS会提供支持。下文将要描述的是TCP协议版本的协议。

RTMP协议的概要理解:

RTMP协议是为了和flash之间交换信令以及媒体数据。为了提高使用效率信令和媒体数据都是使用相同的机制。因为是相同的机制Adobe就整出来了一些比较搞人的概念,当然每个协议第一次接触都是比较难理解的。

在RTMP协议中信令和媒体数据都称之为Message,在网络中传输这些Message,为了区分它们肯定是要加一个Message head的,所以RTMP协议也有一个Message head,还有一个问题因为RTMP协议是基于TCP的,由于TCP的包长度是有限制的(一般来说不超过1500个字节),而RTMP的Message长度是有可能很大的,像一个视频帧的包可能会有几十甚至几千K,这个问题就必然有一个分片的问题,在RTMP协议中对应的说法就是chunk,每一个Message + head都是由一个和多个chunk组成的。到这里对RTMP协议的概要理解就算完了。

RTMP的字节序:
       RTMP的字节序和大多数网络协议一样是大端序,也有一些字段是小端序的,不过都有特殊的说明。
RTMP的head组成

RTMP的head在协议中的表现形式是chunk head,前面已经说到一个Message + head可以分成一个和多个chunk,为了区分这些chunk,肯定是需要一个chunk head的,具体的实现就把Message head的信息和chunk head的信息合并在一起以chunk head的形式表现。

一个完整的chunk的组成如下图所示

Chunk basic header:

该字段包含chunk的stream ID和 type 。chunk的Type决定了消息头的编码方式。该字段的长度完全依赖于stream ID,该字段是一个可变长的字段。

Chunk Msg Header:0, 3 ,7, 11

该字段包含了将要发送的消息的信息(或者是一部分,一个消息拆成多个chunk的情况下是一部分)该字段的长度由chunk basic header中的type决定。

Extend Timestamp: 0 ,4 bytes

该字段发送的时候必须是正常的时间戳设置成0xffffff时,当正常时间戳不为0xffffff时,该字段不发送。当时间戳比0xffffff小该字段不发送,当时间戳比0xffffff大时该字段必须发送,且正常时间戳设置成0xffffff。

Chunk Data
        实际数据(Payload),可以是信令,也可以是媒体数据。

Chunk basic header:
   chunk basic head的长度为1~3个字节,具体长度主要是依赖chunk stream ID的长度,所谓chunk stream ID是flash server用来管理连接的客户端的信令交互的标识,在red5的文档中称之为channel ID,协议最大支持65597个streamID 从3~65599。ID 0,1,2为协议保留,0代表ID是64~319(第二个byte + 64);1代表chunk stream ID为64~65599((第三个byte)* 256 + 第二个byte + 64)(小端表示);2代表该消息为低层的协议(在RTMP协议中控制信令的chunk stream ID都是2)。3~63的chunk stream ID就是该byte的值。没有附加的字段来标识chunk stream streamID。在这里要指出的是虽然RTMP的chunk stream ID理论是可以达到65599,但是目前使用的chunk stream ID很少,2~7都是约定的,8是用来传输publish play等命令,其他的chunk stream ID目前好像没有使用,至少我不知道用来干嘛的。
      所以目前chunk basic head的长度一般为1个字节。这一个字节由两部分组成
                           +++++++++++++++++++
                            +fmt    + cs id               +
                            +++++++++++++++++++
      fmt占两个bit用来标识紧跟其后的chunk Msg Header的长度,cs id占六个bit。
      两位的fmt取值为 0~3,分别代表的意义如下:
      case 0:chunk Msg Header长度为11;
      case 1:chunk Msg Header长度为7;
      case 2:chunk Msg Header长度为3;
      case 3:chunk Msg Header长度为0;
      所以 只有一个字节的chunk basic header取值为 chunk basic header = (fmt << 6) | (cs id).

Chunk Msg Header:

Chunk Msg Header的长度是可变的,Chunk Msg Header可变的原因是为了压缩传输的字节数,把一些相同类型的chunk的head去掉一些字节,换句话说就是四种类型的包头都可以通过一定的规则还原成11个字节,这个压缩和还原在RTMP协议中称之为复用/解复用。

那我们以11个字节的完整包头来解释Chunk Msg Header,如图所示

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

+        timestamp    +    message length + message type id +    message stream id +

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Timestamp:3bytes

对于type 0的chunk,绝对时间戳在这里表示,如果时间戳值大于等于0xffffff(16777215),该值必须是0xffffff,且时间戳扩展字段必须发送,其他情况没有要求。

message length:3bytes

Message的长度,注意这里的长度并不是跟随chunk head其后的chunk data(Payload)的长度,而是前文提到的一条信令或者一帧视频数据或音频数据的长度。前文提到过信令或者媒体数据都称之为Message,一条Message可以分为一条或者多条chunk。

message type id:1byte

Message的类型ID,具体的值将在后文专门来讨论。

message stream id:4bytes

message stream id的字节序是小端序,这个字段是为了解复用而设计的,RTMP文档上说的相当的模糊,

message stream ID可以使任意值,不同的消息流复用成相同的chunk stream,基于它们的ID能够解复用。于chunk stream 是相关的,这个字段是一个不透明的值没有整明白什么意思,我的理解就是用来标识和服务器连接的flash端的序号。

长度是7 bytes 的chunk head,该类型不包含stream ID,该chunk的streamID和前一个chunk的stream ID是相同的,变长的消息,例如视频流格式,在第一个新的chunk以后使用这种类型,注意其中时间戳部分是相对时间,为何上一个绝对时间之间的差值 如图所示:

++++++++++++++++++++++++++++++++++++++++++++++++++++++

+     timestamp    delta    +    message length + message type id +

++++++++++++++++++++++++++++++++++++++++++++++++++++++

3 bytes的chunk head,该类型既不包含stream ID 也不包含消息长度,这种类型用于stream ID和前一个chunk相同,且有固定长度的信息,例如音频流格式,在第一个新的chunk以后使用该类型。如图所示:

++++++++++++++++++++

+     timestamp    delta    +

++++++++++++++++++++

0 bytes的chunk head,这种类型的chunk从前一个chunk得到值信息,当一个单个消息拆成多个chunk时,这些chunk除了第一个以外,其他的都应该使用这种类型,

chunk的长度:

chunk的长度初始长度固定为128个字节,但是这个值并不是不可变的,在客户端和服务端建立连接以后,客户端和服务端都可以通过发送信令的方式来通知对端修改chunk的长度,理论上来说可以修改chunk的最长长度为65536。这里chunk的长度是指chunk的数据部分的长度,即chunk data(payload)的长度,如果一条Message的数据长度超过了chunk的长度,就必须把Message分割成多条chunk,即如果一条视频类型Message长度为2000个byte,chunk长度为1500,则该Message将会分割成两条chunk,第一条的chunk data长度为1500,第二条的chunk data长度为500。当然这两条chunk的chunk head肯定是不同的,其中第二条chunk的chunk head就是0字节的。

 

RTMP协议详解(转)的更多相关文章

  1. rtmp 协议详解

    1. handshake 1.1 概述 rtmp 连接从握手开始.它包含三个固定大小的块.客户端发送的三个块命名为 C0,C1,C2:服务端发送的三个块命名为 S0,S1,S2. 握手序列: 客户端通 ...

  2. HTTP协议详解(转)

    转自:http://blog.csdn.net/gueter/archive/2007/03/08/1524447.aspx Author :Jeffrey 引言 HTTP是一个属于应用层的面向对象的 ...

  3. HTTP协议详解

    Author :Jeffrey 引言 HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展. ...

  4. 动态选路、RIP协议&&OSPF协议详解

    动态选路.RIP协议&&OSPF协议详解 概念 当相邻路由器之间进行通信,以告知对方每个路由器当前所连接的网络,这时就出现了动态选路.路由器之间必须采用选路协议进行通信,这样的选路协议 ...

  5. ASP.NET知识总结(3.HTTP协议详解)

    引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...

  6. 接口测试之HTTP协议详解

    引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...

  7. 计算机网络(12)-----HTTP协议详解

    HTTP协议详解 http请求 http请求由三部分组成,分别是:请求行.消息报头.请求正文 (1)请求行 请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Metho ...

  8. OSPF协议详解

    CCNP OSPF协议详解 2010-02-24 20:30:22 标签:CCNP 职场 OSPF 休闲 OSPF(Open Shortest Path Fitst,ospf)开放最短路径优先协议,是 ...

  9. HTTP协议详解(真的很经典)

    HTTP 是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和 扩展.目前在WWW中使用的是HTTP/1.0 ...

随机推荐

  1. httpclient 人人网

    登录的站点是3g.renren.com 因为是手机人人, 页面比较简单 首先用HttpGet取出"http://3g.renren.com"的html代码, 是用Jsoup解析出登 ...

  2. Oracle RAC 常用维护工具和命令

    Oracle RAC 常用维护工具和命令 分类: Oracle Basic Knowledge Oracle RAC2010-03-09 01:02 13987人阅读 评论(6) 收藏 举报 orac ...

  3. ZOJ1232 Adventure of Super Mario spfa上的dp

    很早之前听说有一种dp是在图上的dp,然后是在跑SPFA的时候进行dp,所以特地找了一题关于在SPFA的时候dp的. 题意:1~a是村庄 a+1~a+b是城堡,存在m条无向边.求由a+b->1的 ...

  4. 【hadoop2.6.0】用C++ 编写mapreduce

    hadoop通过hadoop streaming 来实现用非Java语言写的mapreduce代码. 对于一个一点Java都不会的我来说,这真是个天大的好消息. 官网上hadoop streaming ...

  5. android Notification定义与应用

    首先要明白一个概念: Intent 与 PendingIntent 的区别: Intent:是意图,即告诉系统我要干什么,然后做Intent应该做的事,而intent是消息的内容 PendingInt ...

  6. 安卓--使用Intent实现Activity之间传值与跳转

    http://blog.csdn.net/cjjky/article/details/6337447 在一个Android的应用程序中,很少只存在一个Activity,一般都有多个Activity,如 ...

  7. ARM CPU与Intel x86 CPU性能比较

    Qualcomm ARM CPU与Intel x86 CPU性能比较 随着移动互联网时代的到来,Qualcomm(高通).Texas Instruments(德州仪器)等基于ARM架构的CPU受到越来 ...

  8. VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)

    原文地址: VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)-软件开发-鸡啄米 http://www.jizhuomi.com/software/139.html   上一讲中鸡 ...

  9. dubbo-admin管理平台搭建

    参考:http://blog.csdn.net/u013142781/article/details/50396621 一.前言 dubbo的使用,其实只需要有注册中心,消费者,提供者这三个就可以使用 ...

  10. Mmap的实现原理和应用

    http://blog.csdn.net/edwardlulinux/article/details/8604400 很多文章分析了mmap的实现原理.从代码的逻辑来分析,总是觉没有把mmap后读写映 ...