AMF(Action Message Format),即操作消息格式,基于http方式传输,是一种二进制的数据格式。主要用于数据交互和远程过程调用。它的设计是为了把actionscript里面的数据(包括Object, Array, Boolean, Number等)序列化成二进制数据,然后把这段数据随意发送给其他接收方程序,比如发给远程的服务器,在远程服务器那边,可以把这段数据给还原出来,以此达到一个数据传输的作用。
AMF引进于2001年的FlashPlayer6,并且在引入AS2.0的FlashPlayer7和FlashPlayer8中没有改变的保留了。这个版本的AMF参考于AMF0(查阅[AMF0])。在FlashPla yer9中,AS3.0同新的AS虚拟机(AVM+)一起被引进—新的数据类型和语言特性的改进致使AMF升级成为可能,给了一个发布新的AMF版本的机会,新版本的AMF在序列化数据的时候做了一些优化,使得编码格式去除了一些冗余信息。升级后的AMF版本便是AMF3。
第一个版本的AMF,即AMF0,支持在避免了在对象图中发送冗余的实例的通过引用发送复杂的对象。他也允许端点存储对象关系,并且支持避免一些问题,在序列化时无穷的递归的情况下的循环引用。新版本的AMF,即AMF3,与AS3.0(ActionScript 动作脚本)版本保持一致,在通过引用发送除对象实例外的对象特性和字符串做了改进。AMF3也支持在AS3.0中的一些新的数据类型。
那么AMF3出来之后AMF0是不是可以退休了?答案也是否定的。大家现在接触到的AMF3消息流基本上都是在AMF3外面包了一层AMF0, 也就是说我们看到的所有AMF数据流都是AMF0的,当数据流中的某个数据的type=0×11时,才表示这个数据应该属于AMF3的数据,在这个时候就会切换到AMF3的模式来处理这个数据。处理完之后当然还是继续回到AMF0的模式处理数据。
通常情况下我们使用JSON或者XML来做数据的传输,他们的好处是文本数据易读、容易修改,坏处在于文本数据体积较大,而且数据的组织有其局限性。同样是轻量级数据交换协议,同样是通过调用远程服务,同样是基于标准的HTTP和HTTPS协议, Flash Remoting为什么选择了使用AMF而放弃了SOAP与Flash 播放器通信呢? 有如下原因:
AMF分成两种:AMF0,基本的数据转换规则;AMF3,是AMF0的扩展。
// AMF0数据类型;
typedef enum
{
AMF_NUMBER = 0, // 数字(double);
AMF_BOOLEAN, // 布尔;
AMF_STRING, // 字符串;
AMF_OBJECT, // 对象;
AMF_MOVIECLIP, // 保留,未使用;
AMF_NULL, // null;
AMF_UNDEFINED, // 未定义;
AMF_REFERENCE, // 引用;
AMF_ECMA_ARRAY, // 数组;
AMF_OBJECT_END, // 对象结束;
AMF_STRICT_ARRAY, // 严格的数组;
AMF_DATE, // 日期;
AMF_LONG_STRING, // 长字符串;
AMF_UNSUPPORTED, // 未支持;
AMF_RECORDSET, // 保留,未使用;
AMF_XML_DOC, // xml文档;
AMF_TYPED_OBJECT, // 有类型的对象;
AMF_AVMPLUS, // 需要扩展到AMF3;
AMF_INVALID = 0xff // 无效的;
}AMFDataType;
// AMF3数据类型;
typedef enum
{
AMF3_UNDEFINED = 0, // 未定义;
AMF3_NULL, // null;
AMF3_FALSE, // false;
AMF3_TRUE, // true;
AMF3_INTEGER, // 数字int;
AMF3_DOUBLE, // double;
AMF3_STRING, // 字符串;
AMF3_XML_DOC, // xml文档;
AMF3_DATE, // 日期;
AMF3_ARRAY, // 数组;
AMF3_OBJECT, // 对象;
AMF3_XML, // xml;
AMF3_BYTE_ARRAY // 字节数组;
} AMF3DataType;
// AMF自定义的字符串;
typedef struct AVal
{
char *av_val;
int av_len;
} AVal;
// AMF对象, 就是由一系列的属性构成的;
typedef struct AMFObject
{
int o_num; // 属性数目;
struct AMFObjectProperty *o_props; // 属性数组;
} AMFObject;
AMFObject表示AMF对象,o_num 代表 o_props的个数, 一个对象内部可以包含N个对象属性;
// AMF对象的属性;
typedef struct AMFObjectProperty
{
AVal p_name; // 属性名称;
AMFDataType p_type; // 属性类型;
union
{
double p_number;
AVal p_aval;
AMFObject p_object;
} p_vu; // 属性数值;
int16_t p_UTCoffset; // UTC偏移;
} AMFObjectProperty;
AMFObjectProperty表示AMF对象属性,即key-value键值对。p_name表示key;p_type表示value的类型;p_vu表示value的数值。p_vu设置为联合体的目的:
(6)AMF的初始化和字符串比较
// AVal的快速初始化;
#define AVC(str) {str, sizeof(str)-1}
// 比较AVal字符串;
#define AVMATCH(a1,a2) ((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len))
AMF协议是基于Http协议的,它的内容处理过程大致是这样: