我目前正在开发一个小型AMF3适配器,因此试图实现AMF3协议。不幸的是,可用的规范似乎与现实大不相同(捕获AMF与BlazeDS的通信并查看BlazeDS的源代码)。
AMF0规格:http://opensource.adobe.com/wiki/download/attachments/1114283/amf0_spec_121207.pdfAMF3规格:http://opensource.adobe.com/wiki/download/attachments/1114283/amf3_spec_05_05_08.pdf
不幸的是,两者都没有指定实际的消息格式(Header, Body,…)。于是我又搜索了一下,找到了维基百科上的一篇文章:http://en.wikipedia.org/wiki/Action_Message_Format这篇文章,尤其是示例部分似乎描述了一种完全不同的格式。
当查看通信并逐步通过BlazeDS代码时,我可以看到消息声称是AMF3,但使用AMF0中定义的类型代码(0x0a是严格的数组而不是对象,如AMF3中定义的)。
谁能给我解释一下这乱七八糟的东西?目前,我可能只是简单地使用wireshark和BlazeDS代码,以某种方式为我逆向工程协议描述,但我不知道为什么没有一个有效的规范可用。AMF的核心只是一个ActionScript对象序列化格式。
Flash的NetConnection API扩展了这种格式,通过一个简单的报头/消息体请求/响应结构来添加基本的RPC功能,该结构在amf0规范的第4节中描述。我认为这个RPC添加可能会使您感到困惑,因为它是定义如何从服务器发送和接收AMF数据的各个有效负载的基础设施。这个包装器在通过ByteArray进行基本ActionScript对象序列化时不起作用。例如,writeObject。它是基于NetConnection与服务器通信的附加逻辑。见:http://download.macromedia.com/pub/labs/amf/amf0_spec_121207.pdf
ActionScript数据实际发送头值或消息体值在AMF编码。为了兼容性起见,所有数据值都以amf0开头。这可能是人们在比较基本AMF序列化与基于NetConnection的通信时首先遇到的另一个问题。由于在amf0中添加了一个特殊扩展,引入了一个新的0x11"amf3"模式标记,将序列化模式切换到amf3。不支持AMF 3的遗留客户机将无法理解这个新的标记,并将停止处理数据。这在amf0规范的第3节中提到。
amf3规范如下:http://download.macromedia.com/pub/labs/amf/amf3_spec_121207.pdf
有两种一般类型的AMF消息传递:AMF0样式的RPC调用和RTMP。AMF0 RPC调用由版本、头列表和消息列表组成,它们大致相当于要调用的方法。这在AMF0规范的末尾有文档记录,可用于进行AMF0或AMF3远程调用。如果您正在使用Flex RemoteObject,那么Flex在消息传递中还会使用一些额外的包装器对象。第二种类型是RTMP使用的消息格式,它是AMF和它自己的自定义格式的组合。据我所知,这种格式没有规范。
作为构建了可以解析AMF并进行RPC调用的库(RocketAMF)的人,我建议您使用现有的库之一,而不是编写自己的库,如果您只是需要远程支持。下面是按语言进行AMF解析的一些库的列表,还有更多的库可以通过简单的搜索获得。您可能还想检查一下Charles,它能够对通过它代理的AMF请求进行反序列化,使逆向工程更容易一些。
- Python: PyAMF
- Ruby: RocketAMF
- Java: BlazeDS
- PHP: Zend:: AMF