您的位置:首页 > 运维架构 > Apache

RED5和APACHE MINA及握手

2013-09-28 14:46 204 查看
转自:http://hi.baidu.com/janins/item/7fdcb5735d1dfb10d1dcb3ba

1. RED5和APACHE MINA



Red5采用的网络编程框架是Apache Mina。所以源码研究的思路可以有:

1) 从Mina的角度进行请求处理流的研究。

2) 从Red5整体管理角度进行Red5的应用框架研究。

3) 从一些核心的处理环节进行研究,例如编解码、录制、回放和直播。

2. 从MINA的角度看RED5的请求处理流(仅仅分析RTMP)

2.1. 建立基于MINA的网络监听





上面完全是Mina的网络特性,就是建立网络监听。

2.2. 通过实现MINA的IOHANDLER引入网络连接管理





SessionCreated回调中来添加Session级别的编码过滤器,同时构建自己的链接管理对象RTMPMinaConnection,注意上面关于握手的代码,其已经涉及到RTMP协议本身,后面我们马上会介绍。



sessionOpened中调用了Red5自己的回调机制,这是把Mina的机制交给Red5机制的一个过渡。

2.3. RED5自己接管网络管理





在链接打开之后,Red5通过启动一个计时器去检测是否握手成功,所谓的握手是RTMP协议中的一个概念,ADOBE已经开放该协议,具体细节请参考http://www.adobe.com/devnet/rtmp/,70页左右,应该比较好理解。Red5对握手的实现就是在一个Session打开之后通过在一段固定时间去内读取握手信息,如果超过该固定时间还没有握手成功,将直接断开客户端链接。也就是当Red5接管链接之后第一件事情就是读取用户信息进行握手操作。那么握手首先要读取数据,我们先进入读取数据的环节。

2.4. RED5和客户端进行握手





上面的代码我们基本能看到,当客户端有数据发送过来的时候,首先判断输入的数据是否是Mina的原始数据类型IoBuffer,如果是那么由红色标线的方法去处理,其实红色标线的处理就是进行握手操作。如下代码:



握手成功之后Red5才进入正式的数据读取和处理状态。那我们要问的是为什么判断数据类型是IoBuffer就代表是还没有握手呢?原因我们可以追溯到在SessionCreated阶段时添加的Codec过滤器,Red5的Codec工厂对没有握手的链接是仅仅进行IoBuffer的数据准备,并不进行协议解析。

为了让握手的过程更加清晰我们先看看RTMP协议:

RTMP协议在客户端发起链接时首先要进行一个握手过程,至于握手的目的是什么?我个人认为就是相互通个气,看看是否客户端和服务器端都能读懂RTMP,不能糊里糊涂的就连上。

RTMP的握手在协议中叫Handshake,其过程如下:

1) 首先客户端在建立链接的时候向服务器端发送两个固定长度的数据块(C0,C1)。

2) 然后客户端必须接收到S1之后,才能发送C2。

3) 客户端接收到服务器的S2之后,才能发送其他数据。

4) 服务端必须在接收到C0之后,才能发送(S0,S1),也可以在另外再等待同时接收到C1之后再发。
5) 服务端必须在接收到C1之后,才能发送S2。

6) 服务端必须在接收到C2之后,才能发送其他数据。

其中数据格式要求如下:

C0和S0的格式是一样的,由8位表示的数字3组成(RTMP1.0的定义)。

C1和S1由1536字节组成,只有对前面的8字节有特殊要求,后面的数据都由随机位组成。

C2和S2也有1536字节组成,并且对前面的8字节有特殊要求,后面的数据都由随机位组成。







Time2 (4 bytes): This field MUST contain the timestamp at which the previous packet(s1 or c1) sent by the peer was read.



Red5的具体实现过程可以参考阅读如下代码:



在generateResponse中我们疑惑的是其一次性进行握手的操作,那么数据是如何缓冲到位的呢?这也是Mina的Codec过滤器机制的重要作用体现,请阅读红线标注的方法实现:



RTMPProctocolDecoder获取不到完整的握手数据它根本不交给后端进行处理,这也给我们一个思路就是在Mina基础上开发的时候如何通过Codec过滤器实现让后端的应用不要太依赖网络数据的特性。

其实在上面红线标注的方法中有两次进行握手信息的解析,第一次是C0和C1,第二次是C2。

评价:其实仔细看Red5的代码,我个人并不觉得Red5的一些细节设计有多合理, 既然握手是RTMP是否建立成功的一部分,那么Red5就不应该把其直接放到RTMPHandler中作为一个事件connectionOpened来调用,其实调用了也没起什么作用,仅仅启动一个判断是否超时的计划任务,恰恰造成的后果是在RTMP层面,一个连接完全建立成功,即握手成功之后并没有事件抛出。再仔细看引入RTMPHandler的意义并不大,还不如直接在RTMPMinaIoHandler中解决问题,引入只是给人造成迷惑,Mina清晰的架构被RTMPHandler和RTMPMinaIoHandler的引入搞的有点不可读。还有Red5把客户端和服务器端代码的分离的方法也值得商讨,其实严格意义上说RTMP的客户端和服务器端共享的应该是RTMP协议部分,而不是基于Mina的网络处理部分,我们仔细看Red5,其实包org.red5.server中的代码弄了很多既满足客户端又满足服务器端的东东,真让人费解。那如何分离出来独立的服务器端和客户端的API呢?

2.5. RED5开始接收数据

当握手完成之后,Red5的Codec过滤器将会起作用,同时Red5在接收到数据的时候直接路由到其自己的处理器。



在红线标注的方法中我们可以看到Red5进入具体RTMP协议路由。

从Mina的角度Red5对RTMP的请求处理流就是这样了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: