ghdhair100
Ununokt
Dołączył: 15 Gru 2010
Posty: 1876
Przeczytał: 0 tematów
Ostrzeżeń: 0/5 Skąd: England
|
Wysłany: Śro 12:33, 02 Mar 2011 Temat postu: AMF学习 |
|
|
我是做.Net开发的,按理说和AMF没有什么关系,主要是最近在耍一款网页游戏:纵横天下,该游戏就是采用Flex做的客户端,为了能够做出该游戏的挂机程序,所以才开始学习研究AMF的。闲话休说,言归正传,下面继续说AMF协议,在例子中我使用的AMF数据就是从纵横天下中抓取的AMF数据。
以上是客户端向服务器发送的一个AMF请求。我们可以按照前面说的封装方式将该amf解析如下:
00 00 00 13(主体的长度为19)
现在我们已经对AMF文件有了一个清晰的认识了。那么接下来就是要抓包,看某些在Flex上的操作对应的发送了什么AMF文件,服务器返回了什么AMF文件。将这些AMF文件解析出来然后就可以看到调用了API了。
说了这么多估计还是感觉比较抽象,下面给出个实例:
第3和第4字节用16位整数表示AMF头的数量。
AMF文件总体来说分为4部分:前言(Preamble)、AMF头、AMF主体和主体的响应。
00 1B(请求的方法的字符串长度为27个字节)
AMF 16进制内容
Int32- 表示主体的长度,该字段一般没有什么用
主体响应是客户端向服务器发送一个AMF请求以后服务器做出的和请求的主体格式相同的AMF响应,但是主体响应中的内容有所不同:
AMF目前有两种版本,AMF0和AMF3,他们在数据类型的定义上有细微不同。关于AMF的官方文档参见这里。
前一篇文章中已经学习了AMF数据类型,那么接下来就要将一个完整的AMF文件的封装格式了。
Variable变量表示主体的数据。
Response: 被设置为字符串‘null’.
AMF3 data0×11Sent by Flash player 9+ 对应的枚举就是public enum DataType
{
Number = 0,
Boolean = 1,
String = 2,
UntypedObject = 3,
MovieClip = 4,
Null = 5,
Undefined = 6,
ReferencedObject = 7,
MixedArray = 8,
End = 9,
Array = 10,//0x0A
Date = 11,//0x0B
LongString = 12,//0x0C
TypeAsObject = 13,//0x0D
Recordset = 14,//0x0E
Xml = 15,//0x0F
TypedObject = 16,//0x10
AMF3data=17//0x11
} 以上表列出了每种数据类型的表示方法,这样看并不容易理解,下面我就主要讲解一下常用的一些格式:0.Number这里指的是double类型,数据用8字节表示,比如十六进制00 40 10 00 00 00 00 00 00就表示的是一个double数4.0,在C#中可以使用如下代码读取该数据: byte[] d=new byte[]{0,0,0,0,0,0,0x10,0x40};//这里的顺序是和amf文件中的顺序正好相反,不要忘记了
double num=BitConverter.ToDouble(d,0); 1.Boolean对应的是.net中的bool类型,数据使用1字节表示,和C语言差不多,使用00表示false,使用01表示true。比如十六进制01 01就表示true。 2.String相当于.net中的string类型,String所占用的空间有1个类型标识字节和2个表示字符串UTF8长度的字节加上字符串UTF8格式的内容组成。比如十六进制03 00 08 73 68 61 6E 67 67 75 61表示的就是字符串,该字符串长8字节,字符串内容为73 68 61 6E 67 67 75 61,对应的就是“shanggua”。在C#中要读取字符串则使用: byte[] buffer=new byte[]{0x73,0x68,0x61,0x6E,0x67,0x67,0x75,0x61};//03 00 08 73 68 61 6E 67 67 75 61
string str=System.Text.Encoding.UTF8.GetString(buffer);
3.Object在.net中对应的就是Hashtable,内容由UTF8字符串作为Key,其他AMF类型作为Value,该对象由3个字节:00 00 09来表示结束。C#中读取该对象使用如下方法: private Hashtable ReadUntypedObject()
{
Hashtable hash = new Hashtable();
string key = ReadShortString();
for (byte type = ReadByte(); type != 9; type = ReadByte())
{
hash.Add(key, ReadData(type));
key = ReadShortString();
}
return hash;
}
5.Null就是空对象,该对象只占用一个字节,那就是Null对象标识0x05。 6. Undefined 也是只占用一个字节0x06。 8.MixedArray相当于Hashtable,与3不同的是该对象定义了Hashtable的大小。读取该对象的C#代码是:
Variable变量是某种AMF数据类型。
AMF学习2远程调用的封装[转]
每一个AMF头是由以下四部分组成:
Int32表示Header的长度,但是好像很多情况下该值为FF FF FF FF,似乎这个字段没有意义。
12.LongString对应的也是string类型,不过和2对应的String不同的是这里使用32位整数来表示字符串的UTF8长度,而String使用的是16位。
UTF string 表示Header的名字
前言的前2字节用于说明AMF的版本,目前AMF有2个版本AMF0和AMF3.如使用AMF0则是:00 00
AMF是Action Message Format协议的简称,AMF协议是Adobe公司自己的协议,主要用于数据交互和远程过程调用,在功能上相当于WebService,但是AMF与WebService中的XML不同的是AMF是二进制数据,而XML是文本数据,AMF的传输效率比XML高。AMF使用HTTP方式传输,目前主要是用于ActionScript中,即实现Flex和Server之间的通信。
现在整个AMF对象都解析出来了,我们可以认为是客户端调用了服务器的方法:zh.fleetService.getFleetRow("5", "845", "5")
0×10
0A(传入的变量是一个Array)00 00 00 03(该Array的长度为3)02 00 01 35(Array的第一个值是字符串“5”)02 00 03 38 34 35(Array的第二个值是字符串“845”)02 00 01 35(Array的第三个值是字符串“5”)
11.Date对应.net中的DateTime数据类型,Date在类型标识符0x0B后使用double来表示从1970/1/1到表示的时间所经过的毫秒数,然后再跟一个ushort的16位无符号整数表示时区。读取Date类型的C#代码为:
private DateTime ReadDate()
{
double ms = ReadDouble();
DateTime BaseDate = new DateTime(1970, 1, 1);
DateTime date = BaseDate.AddMilliseconds(ms);
ReadUInt16(); //get's the timezone
return date;
}
private Hashtable ReadDictionary()
{
int size = ReadInt32();
Hashtable hash = new Hashtable(size);
string key = ReadShortString();
for (byte type = ReadByte(); type != 9; type = ReadByte())
{
object value = ReadData(type);
hash.Add(key, value);
key = ReadShortString();
}
return hash;
}
在Header表示完后,接下来是一个16位的整数用来表示AMF主体的数量,在这个数量之后才是AMF主体。
00 00(AMF0版本)00 00(Header个数为0)00 01(AMF主体有1个)
15.XML是使用类型标识符0x0F后直接跟LongString类型的字符串表示。
private ArrayList ReadArray()
{
int size = ReadInt32();
ArrayList arr = new ArrayList(size);
for (int i = 0; i < size; ++i)
{
arr.Add(ReadData(ReadByte()));
}
return arr;
}
服务器返回的AMF文件的内容的解析方式相同,这里我就不再重复了。
00000000h: 00 00 00 00 00 01 00 1B 7A 68 2E 66 6C 65 65 74 ; ........zh.fleet
00000010h: 53 65 72 76 69 63 65 2E 67 65 74 46 6C 65 65 74 ; Service.getFleet
00000020h: 52 6F 77 00 03 2F 37 39 00 00 00 13 0A 00 00 00 ; Row../79........
00000030h: 03 02 00 01 35 02 00 03 38 34 35 02 00 01 35 ; ....5...845...5
UTF String - Target是一个标识,其作用就是为了实现请求和响应的对应,通过Target找到该响应对应的请求。一般使用自增整数。
7A ……77(这27个直接就是调用的类和方法:“zh.fleetService.getFleetRow”)
Data:就是响应后返回的AMF对象。
Boolean 表示该Header是否是必须的
10.Array对应的就是.net中的ArrayList对象,该对象首先使用32位整数定义了ArralyList的长度,然后是密集的跟着ArrayList中的对象,读取该对象使用如下函数:
00 03(请求的Target字符串长3字节) 2F 37 39(Target的内容:“/79”)
UTF String - Response表示请求的类和方法或响应的结果。
AMF主体主要由以下四部分组成:
AMF学习1数据类型[转]
Target: 是请求的Target值再加上“/onStatus”, “onResult”, 或者 “/onDebugEvents”组成. “/onStatus” 是为运行时错误而准备的我们一般不关心这个. “/onResult” 表示该请求被正确调用. “/onDebugEvents” 是在调试时使用的,这里也不用关心. 如果请求的Target是‘/1’, 那么被成功调用以后的主体响应应该是: ‘/1/onResult’ 。
这里大部分代码我都是摘自AMF.net 一个开源的.net AMF序列化和反序列化的库,大家若有兴趣可以到http://sourceforge.net/project/showfiles.php?group_id=159742 去下载。另外http://osflash.org/documentation/amf/astypes 这个英文网站也对AMF数据类型作了比较详细的介绍。
TypeByte codeNotesNumber0×00Boolean0×01String0×02Object0×03MovieClip0×04Not available in RemotingNull0×05Undefined0×06Reference0×07MixedArray0×08EndOfObject0×09See ObjectArray0x0aDate0x0bLongString0x0cUnsupported0x0dRecordset0x0eRemoting, server-to-client onlyXML0x0fTypedObject (Class instance)Many years ago there lived an Emperor who was so exceedingly fond of fine new clothes that he spent vast sums of money on dress. To him clothes meant more than anything else in the world. He took no interes
related links:
[link widoczny dla zalogowanych]
Post został pochwalony 0 razy
|
|