AMF是Action Message Format協議的簡稱,AMF協議是Adobe公司自己的協議,主要用於資料互動和遠端程序呼叫,在功能上相當於WebService,但是AMF與WebService中的XML不同的是AMF是位元據,而XML是文本資料,AMF的傳輸效率比XML高。AMF使用HTTP方式傳輸,目前主要是用於ActionScript中,即實現Flex和Server之間的通訊。
我是做.Net開發的,按理說和AMF沒有什麼關係,主要是最近在耍一款網頁遊戲:縱橫天下,該遊戲就是採用Flex做的用戶端,為了能夠做出該遊戲的掛機程式,所以才開始學習研究AMF的。閑話休說,言歸正傳,下面繼續說AMF協議,在例子中我使用的AMF資料就是從縱橫天下中抓取的AMF資料。
AMF目前有兩種版本,AMF0和AMF3,他們在資料類型的定義上有細微不同。關於AMF的官方文檔參見這裡。
| Type |
Byte code |
Notes |
| Number |
0×00 |
|
| Boolean |
0×01 |
|
| String |
0×02 |
|
| Object |
0×03 |
|
| MovieClip |
0×04 |
Not available in Remoting |
| Null |
0×05 |
|
| Undefined |
0×06 |
|
| Reference |
0×07 |
|
| MixedArray |
0×08 |
|
| EndOfObject |
0×09 |
See Object |
| Array |
0x0a |
|
| Date |
0x0b |
|
| LongString |
0x0c |
|
| Unsupported |
0x0d |
|
| Recordset |
0x0e |
Remoting, server-to-client only |
| XML |
0x0f |
|
| TypedObject (Class instance) |
0×10 |
|
| AMF3 data |
0×11 |
Sent 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 物件,該對象只佔用一個位元組,那就是Null對象標識0x05。 6. Undefined 也是只佔用一個位元組0x06。 8.MixedArray相當於Hashtable,與3不同的是該對象定義了Hashtable的大小。讀取該對象的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;
}
10.Array對應的就是.net中的ArrayList對象,該對象首先使用32位整數定義了ArralyList的長度,然後是密集的跟著ArrayList中的對象,讀取該對象使用如下函數:
private ArrayList ReadArray()
{
int size = ReadInt32();
ArrayList arr = new ArrayList(size);
for (int i = 0; i < size; ++i)
{
arr.Add(ReadData(ReadByte()));
}
return arr;
}
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;
}
12.LongString對應的也是string類型,不過和2對應的String不同的是這裡使用32位整數來表示字串的UTF8長度,而String使用的是16位。
15.XML是使用類型標識符0x0F後直接跟LongString類型的字串表示。
這裡大部分代碼我都是摘自AMF.net 一個開源的.net AMF序列化和還原序列化的庫,大家若有興趣可以到http://sourceforge.net/project/showfiles.php?group_id=159742 去下載。另外http://osflash.org/documentation/amf/astypes 這個英文網站也對AMF資料類型作了比較詳細的介紹。