一.Flex向Red5服务端发送消息
这里有一个程序是群聊,那么现在其中有一个人像其他人发送以短消息,如“vvvvv”,我们来解析这个过程。
客户端的方法代码
protected functionsendMessage(event:MouseEvent):void
{
// TODO Auto-generated method stub
var sendString:String = txt_yousay.text;
//varsendTo:String=users.selectedItem.userName==null?"":users.selectedItem.userId;
var sendTo:String=userList.selectedItem.label;
txt_yousay.text = "";
conn.call("sayToAll", null,sendTo,sendString);
}
当我们输入完消息,点击发送的时候,就会调用这个方法,其中sendTo使我们要发送的对象,这个程序里的值应该是“All”,sendString的值就是我们输入的消息,这里应该是“vvvvvv”,这些无关紧要,我们只需要知道它的值就行了。
客户端调用conn.call("sayToAll",null,sendTo,sendString);给服务端发送一个消息,表示我们需要调用服务端的一个函数,函数名叫做"sayToAll",还有剩下三个参数,第一个参数是用来保存从服务端返回的数据,这里不需要服务端返回数据,所以设为null,第二第三个参数使我们要给服务端的消息,服务端获取这些数据后,进行处理。
我用wireshark工具截获了rtmp包,下图就是我们发送服务端的RTMP报的内容,我们来分析一下。
上图蓝色区域就是RTMP报的内容,它包括一个包头和包身。
RTMP Header,从43到11这8个字节是包头,来列一张表
RTMP Header |
|
数据 |
解释 |
43 |
01.. .... = Format: 1 ..00 0011 = Chunk Stream ID: 3 |
00 16 9e |
Timestamp delta: 5790 |
00 00 24 |
Body size: 36 |
11 |
Type ID: AMF3 Command (0x11) |
|
|
Rtmp包头网上有很多解释,这里不详细说了,说明一下,
43的前两位为01说明包头是8字节的,最后一个字节11说明这个包的类型是FLEX_MESSAGE
下面来看一下包体。列张表:
RTMP Body |
|
数据 |
解释 |
02 00 08 73 61 79 54 6f 41 6c 6c |
String 'sayToAll' 02 AMF type: String (2) 00 08 String length: 8 73 61 79 54 6f 41 6c 6c String: sayToAll |
00 00 00 00 00 00 00 00 00 |
AMF type: Number (0) Number: 0 |
05 |
AMF type: Null (5) |
02 00 03 41 6c 6c |
String 'All' 02 AMF type: String (2) 00 03 String length: 3 41 6c 6c String: All |
02 00 05 76 76 76 76 76 |
String 'vvvvv' 02 AMF type: String (2) 00 05 String length: 5 76 76 76 76 76 String: vvvvv |
这里我们来分析一下,RTMP头就不说了,我们来看RTMP包的包体,这需要和我们发送的消息关联。conn.call("sayToAll",null,sendTo,sendString);
那么包体的第一部分数据是一个字符串“sayToAll”,说明要调用的服务端的方法,对应方法里的第一个参数;
第二部分数据是一个number型,CallID (double)
第三部分数据为null,说明我们的responder为null,对应方法里的第二个参数
第四部分数据是一个字符串“All”,对应方法里的第三个参数
第五部分数据是一个字符串,对应方法里的第四个参数
。。这里说明一下,如果数据是字符串,那么第一个字节是02表示AMF类型是字符串,后面紧跟的两个字节表示字符串的长度,然后后面是这个长度个字节的字符串类容。
如果数据时number类型的,固定第一个字解释00,表示AMF类型是number,后面跟8字节的值。
二.Red5向Flex客户端发送invoke
服务端要做的事情呢就是向其他所有聊天室的人转发第一个客户发送的消息,服务端需要考苏其他所有客户端调用一个方法,这个方法在自己客户端的页面上显示这条消息。服务端当然还需要传给客户端参数,是谁发的消息,消息内容是什么。
现在服务端循环遍历所有客户端,并且调用下列方法:
sc.invoke("showMessage", newObject[]{clientName+" to All:"+sayWhat});
这个方法里面,"showMessage"是客户端需要调用的方法,new Object[]{clientName+" toAll:"+sayWhat}是服务端传给客户端的参数,在我的实验里,这个参数的值其实就是“ddddto All:vvvvv”。
下面是我们截取的RTMP包,我们来分析一下包。
这个包和我们上面看的包类似的
RTMP Header |
|
数据 |
解释 |
43 |
01.. .... = Format: 1 ..00 0011 = Chunk Stream ID: 3 |
00 00 00 |
Timestamp delta: 0 |
00 00 2c |
Body size: 44 |
14 |
Type ID: AMF3 Command (0x14) |
|
|
这里要注意的是最后一个字节 14,根据AMFType,我们调用的是invoke。
0×14 Invoke like remoting call, used for stream actions too.
看下包体
RTMP Body |
|
数据 |
解释 |
02 00 0b 73 68 6f 77 4d 65 73 73 61 67 65 |
String ' showMessage ' 02 AMF type: String (2) 00 08 String length: 11 73 68 6f 77 4d 65 73 73 61 67 65 String: showMessage |
00 40 10 00 00 00 00 00 00 |
AMF type: Number (0) Number: 4 |
05 |
AMF type: Null (5) |
11 |
AMF type: Switch to AMF3 (17) |
06 23 64 64 64 64 20 74 6f 2041 6c 6c 3a 76 76 76 76 76 |
06 23 不是很清楚,剩下的字节是 String 'dddd to All:vvvvv' |
联系我们的服务端调用的方法,数据的第一部分数据String' showMessage '
就是我们的方法的第一个参数,后面Number:4 为CallID,然后Null似乎是个固定的,没有深究,最后的字符串就是方法里的第二个参数。
到这里flex,red5的通信就分析完了,附上一些有用的url
http://wiki.gnashdev.org/RTMP_Messages_Decoded
http://blog.csdn.net/cssmhyl/article/details/8052794