AMF協(xié)議的數(shù)據(jù)讀取代碼解析
AMF協(xié)議規(guī)定的數(shù)據(jù)在使用HTTP方式傳輸時(shí),用于ActionScript中,為了使Flex和Server能夠完好地通信。但是也有不少人對(duì)這個(gè)不太了解,下面我們對(duì)這方面的數(shù)據(jù)內(nèi)容進(jìn)行一下解析。
AMF協(xié)議是Action Message Format協(xié)議的簡(jiǎn)稱,AMF協(xié)議是Adobe公司自己的協(xié)議,主要用于數(shù)據(jù)交互和遠(yuǎn)程過(guò)程調(diào)用,在功能上相當(dāng)于WebService,但是AMF與WebService中的XML不同的是AMF是二進(jìn)制數(shù)據(jù),而XML是文本數(shù)據(jù),AMF的傳輸效率比XML高。AMF使用HTTP方式傳輸,目前主要是用于ActionScript中,即實(shí)現(xiàn)Flex和Server之間的通信。
AMF目前有兩種版本,AMF0和AMF3,他們?cè)跀?shù)據(jù)類型的定義上有細(xì)微不同。關(guān)于AMF的官方文檔參見(jiàn)這里。
- TypeByte codeNotes
- Number0×00
- Boolean0×01
- String0×02
- Object0×03
- MovieClip0×04Not available in Remoting
- Null0×05
- Undefined0×06
- Reference0×07
- MixedArray0×08
- EndOfObject0×09See Object
- Array0x0a
- Date0x0b
- LongString0x0c
- Unsupported0x0d
- Recordset0x0e Remoting, server-to-client only
- XML0x0f
- TypedObject (Class instance)0×10
- AMF3 data0×11 Sent by Flash player 9+
#p#對(duì)應(yīng)的枚舉就是
- 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}
以上表列出了每種數(shù)據(jù)類型的表示方法,這樣看并不容易理解,下面我就主要講解一下常用的一些格式:
0.Number這里指的是double類型,數(shù)據(jù)用8字節(jié)表示,比如十六進(jìn)制00 40 10 00 00 00 00 00 00就表示的是一個(gè)double數(shù)4.0,在C#中可以使用如下代碼讀取該數(shù)據(jù):
- byte[] d=new byte[]{0,0,0,0,0,0,0x10,0x40};
- //這里的順序是和amf協(xié)議文件中的順序正好相反,不要忘記了double num=BitConverter.ToDouble(d,0);
1.Boolean對(duì)應(yīng)的是.net中的bool類型,數(shù)據(jù)使用1字節(jié)表示,和C語(yǔ)言差不多,使用00表示false,使用01表示true。比如十六進(jìn)制01 01就表示true。
2.String相當(dāng)于.net中的string類型,String所占用的空間有1個(gè)類型標(biāo)識(shí)字節(jié)和2個(gè)表示字符串UTF8長(zhǎng)度的字節(jié)加上字符串UTF8格式的內(nèi)容組成。比如十六進(jìn)制03 00 08 73 68 61 6E 67 67 75 61表示的就是字符串,該字符串長(zhǎng)8字節(jié),字符串內(nèi)容為73 68 61 6E 67 67 75 61,對(duì)應(yīng)的就是“shanggua"。在C#中要讀取字符串則使用:#p#
- 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中對(duì)應(yīng)的就是Hashtable,內(nèi)容由UTF8字符串作為Key,其他AMF協(xié)議類型作為Value,該對(duì)象由3個(gè)字節(jié):00 00 09來(lái)表示結(jié)束。C#中讀取該對(duì)象使用如下方法:
- 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;}
4.Null就是空對(duì)象,該對(duì)象只占用一個(gè)字節(jié),那就是Null對(duì)象標(biāo)識(shí)0x05。
5. Undefined 也是只占用一個(gè)字節(jié)0x06。
6.MixedArray相當(dāng)于Hashtable,與3不同的是該對(duì)象定義了Hashtable的大小。讀取該對(duì)象的C#代碼是:
- 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;}
#p#7.Array對(duì)應(yīng)的就是.net中的ArrayList對(duì)象,該對(duì)象首先使用32位整數(shù)定義了ArralyList的長(zhǎng)度,然后是密集的跟著ArrayList中的對(duì)象,讀取該對(duì)象使用如下函數(shù):
- private ArrayList ReadArray()
- { int size = ReadInt32();
- ArrayList arr = new ArrayList(size);
- for (int i = 0; i < size; ++i)
- {arr.Add(ReadData(ReadByte())); }
- return arr;}
8.Date對(duì)應(yīng).net中的DateTime數(shù)據(jù)類型,Date在類型標(biāo)識(shí)符0x0B后使用double來(lái)表示從1970/1/1到表示的時(shí)間所經(jīng)過(guò)的毫秒數(shù),然后再跟一個(gè)ushort的16位無(wú)符號(hào)整數(shù)表示時(shí)區(qū)。讀取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; }
9.LongString對(duì)應(yīng)的也是string類型,不過(guò)和2對(duì)應(yīng)的String不同的是這里使用32位整數(shù)來(lái)表示字符串的UTF8長(zhǎng)度,而String使用的是16位。
10.XML是使用類型標(biāo)識(shí)符0x0F后直接跟LongString類型的字符串表示。