`

AS AMF说明比较好的一篇

    博客分类:
  • flex
阅读更多

原文 http://www.pixelbender.cn/?p=272

 

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对象标识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数据类型作了比较详细的介绍。
------------------------------------------

前一篇文章 中已经学习了AMF数据类型,那么接下来就要将一个完整的AMF文件的封装格式了。

AMF文件总体来说分为4部分:前言(Preamble )、AMF头、AMF主体和主体的响应。

前言的前2字节用于说明AMF的版本,目前AMF有2个版本AMF0和AMF3.如使用AMF0则是:00 00

第3和第4字节用16位整数表示AMF头的数量。

每一个AMF头是由以下四部分组成:

  • UTF string 表示Header的名字

  • Boolean 表示该Header是否是必须的

  • Int32表示Header的长度,但是好像很多情况下该值为FF FF FF FF,似乎这个字段没有意义。

  • Variable变量是某种AMF数据类型。

    在Header表示完后,接下来是一个16位的整数用来表示AMF主体的数量,在这个数量之后才是AMF主体。

    AMF主体主要由以下四部分组成:

  • UTF String - Response表示请求的类和方法或响应的结果。

  • UTF String - Target是一个标识,其作用就是为了实现请求和响应的对应,通过Target找到该响应对应的请求。一般使用自增整数。

  • Int32- 表示主体的长度,该字段一般没有什么用

  • Variable变量表示主体的数据。

    主体响应是客户端向服务器发送一个AMF请求以后服务器做出的和请求的主体格式相同的AMF响应,但是主体响应中的内容有所不同:

  • Response: 被设置为字符串‘null’.

  • Target: 是请求的Target值再加上“/onStatus”, “onResult”, 或者 “/onDebugEvents”组成. “/onStatus” 是为运行时错误而准备的我们一般不关心这个. “/onResult” 表示该请求被正确调用. “/onDebugEvents” 是在调试时使用的,这里也不用关心. 如果请求的Target是‘/1’, 那么被成功调用以后的主体响应应该是: ‘/1/onResult’ 。

  • Data:就是响应后返回的AMF对象。

    说了这么多估计还是感觉比较抽象,下面给出个实例:

    AMF 16进制内容

    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

    以上是客户端向服务器发送的一个AMF请求。我们可以按照前面说的封装方式将该amf解析如下:

    00 00(AMF0版本)00 00(Header个数为0)00 01(AMF主体有1个)

    00 1B(请求的方法的字符串长度为27个字节)

    7A ……77(这27个直接就是调用的类和方法:“zh.fleetService.getFleetRow”)

    00 03(请求的Target字符串长3字节) 2F 37 39(Target的内容:“/79”)

    00 00 00 13(主体的长度为19)

    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”)

    现在整个AMF对象都解析出来了,我们可以认为是客户端调用了服务器的方法:zh.fleetService.getFleetRow("5", "845", "5")

    服务器返回的AMF文件的内容的解析方式相同,这里我就不再重复了。

    现在我们已经对AMF文件有了一个清晰的认识了。那么接下来就是要抓包,看某些在Flex上的操作对应的发送了什么AMF文件,服务器返回了什么AMF文件。将这些AMF文件解析出来然后就可以看到调用了API了。

    【出自博客园深蓝居 ,转载请注明作者出处】
  •  

    分享到:
    评论

    相关推荐

      java源码资源手机游戏J2ME毕业设计

      java源码资源手机游戏J2ME毕业设计提取方式是百度网盘分享地址

      第5章 存储器管理(笔记整理)

      内容概要:本章节深入探讨了存储器管理和相关概念。首先介绍了存储器的多层次结构,涵盖了寄存器、主存和辅助存储的区别及其功能。接下来讨论了主存储器、寄存器的功能和角色,包括二者如何支持程序运行及数据处理。之后分析了高速缓存和磁盘缓存的运作机制及其优化计算机性能的方式。接着概述了程序的装入、链接、地址绑定、内存保护的技术细节。此外,文章还讲述了存储器管理的高级技巧如对换技术、覆盖技术和不同的分配方式,以及各种存储管理模式的具体实施方式,比如连续分配、分页、分段及段页组合。 适用人群:对操作系统内部工作原理有一定兴趣的计算机专业学生、技术人员及爱好者。 使用场景及目标:适用于课程学习和项目实践中,帮助理解和设计复杂的存储管理系统。通过本文的学习可以达到对操作系统底层存储管理的理解,掌握不同存储分配策略的选择标准和技术应用。 阅读建议:建议逐步阅读每个小节,重点关注各部分内容的实际应用场景及其背后的设计理念。同时,尝试绘制存储层次模型和不同管理策略的工作流程图,加深理解。

      gradle611all.zip.png

      gradle611all.zip.png

      onnxruntime-1.16.0-cp39-cp39-win_amd64.whl

      onnxruntime-1.16.0-cp39-cp39-win_amd64.whl

      C#ASP.NET大型商城系统源码带数据库文档数据库 SQL2008源码类型 WebForm

      ASP.NET大型商城系统源码带数据库文档 1.开发环境:vs2010 + slq2005/2008 2.首先在SQL2005建立一个空白数据库。 3.有VS2010 打开项目,直接调试,根据出现提示建立数据库。 4.第3点出现的页面的管理员用户和密码就是后期软件的登陆帐户和密码。 5.本系统有两套模版,在店铺管理 - 页面设置 这里做修改 6.如果觉得自己的系统是空数据库,想弄成和演示的一样,那就将doc/database下面的数据库直接还原就可以了。 7.还原后的数据库登陆帐户和密码分别是:admin888 admin888

      C#ASP.NET酒店管理系统源码(WPF)数据库 Access源码类型 WinForm

      ASP.NET酒店管理系统源码(WPF) 一、源码特点 采用WPF进行开发的酒店管理系统源码,界面相当美观,功能齐全 二、菜单功能 1、预订登记:可选择入住时间、离店时间、所在城市、证件类型,保存、删除、查询、返回 2、住宿结算:新增入住、保存、删除、查询、返回 3、今日盘点:查询、返回 4、查询统计: 5、房间管理:增加房间类型、删除类型、增加房间、删除房间、保存、返回 6、用户管理:增加用户、删除用户、保存、返回 7、系统配置:基本功能 8、显示当前系统时间等功能的实现

      资源quazip.dll

      资源quazip.dll

      C#汽车货运管理系统源码 货运公司车辆管理系统源码数据库 SQL2008源码类型 WinForm

      汽车货运管理系统源码 货运公司车辆管理系统源码 货运公司管理系统采用winform C# 技术开发,数据库Sqlserver2008R2,同时兼容Mysql。 更新日志: 1.修改新增数据异常。 2.增加安装部署工程。 包括如下功能模块: 一、输入功能: 该系统提供了对基本信息录入、车辆登记录入、车辆各项费用录入、驾驶员登记录入、车辆出回车录入、主卡分卡充值录入、加油登记录入,配件信息录入等的模式录入和表格界面录入。在出现从表信息录入时会出现表格界面的录入方式其录入方式同模式录入方式一样。录入信息时可能会出现相同的信息,为避免重复录入部分字段设置了辅助录入功能,您只需输入几项即可完成录入功能。操作方便快捷,可大大提高您的工作效率。 二、查询功能: 您只需用鼠标点击一下相应节点,就可迅速查询统计销售的情况,根据不同的查询统计条件显示出需要的结果。 三、报表功能: 根据查询或者统计出来的结果生成报表。 四:打印功能: 系统支持打印功能,如想打印信息单击预览报表上的打印按钮即可。 五、安全功能: 进入系统后,单击菜单“系统→工具→用户及权限”可以设置系统的各用

      基于springboot+vue的大学生创业项目的信息管理系统源码数据库文档.zip

      基于springboot+vue的大学生创业项目的信息管理系统源码数据库文档.zip

      numpy-1.25.2-cp311-cp311-linux_armv7l.whl

      numpy-1.25.2-cp311-cp311-linux_armv7l.whl

      STM32神舟III号例程源码SD读卡器(神舟III号-库函数版)

      STM32神舟III号例程源码SD读卡器(神舟III号-库函数版)提取方式是百度网盘分享地址

      numpy-1.20.0-cp37-cp37m-linux_armv7l.whl

      numpy-1.20.0-cp37-cp37m-linux_armv7l.whl

      matplotlib-3.7.5-cp39-cp39-linux_armv7l.whl

      matplotlib-3.7.5-cp39-cp39-linux_armv7l.whl

      onnxruntime-1.16.3-cp38-cp38-win_amd64.whl

      onnxruntime-1.16.3-cp38-cp38-win_amd64.whl

      【node毕业设计】nodejs学院会议纪要管理系统源码(完整前后端+mysql+说明文档).zip

      环境说明: 开发语言:nodejs 框架:Express 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:VS code/HBuilder X

      【小程序毕业设计】自助购药小程序源码(完整前后端+mysql+说明文档+LW).zip

      功能说明: 系统主要包括首页、个人中心、用户管理、商家管理、药品信息管理、药品分类管理、发票信息管理、系统管理等功能模块。 环境说明: 开发语言:Java 服务器:tomcat7及以上 JDK版本:JDK1.8 数据库:mysql 5.7数据库工具:Navicat11及以上 开发软件:eclipse/idea 小程序框架:uniapp/原生小程序 开发工具:HBuilder X/微信开发者

      基于Servlet和JSP实现的登录Demo

      《基于Servlet和JSP实现的登录Demo》项目是一个简单的 Java Web 应用示例,展示了如何使用 Servlet 和 JSP 搭建基础的用户登录功能。项目通过 Java Servlet 处理用户请求,使用 JSP 构建前端页面,并结合 MySQL 数据库验证用户身份。用户可以通过登录页面提交账号和密码,后端接口会对用户输入进行校验,并返回登录结果。本项目适合 Java Web 初学者,旨在帮助学习 Servlet 和 JSP 的基础用法,掌握表单提交、请求转发、数据库连接等关键技术点。项目环境包括 IntelliJ IDEA、Apache Tomcat 和 MySQL,支持 JDK 8 及以上版本。

      (全新整理)中国高校各专业录取分数线、招生计划、分段表数据(2008-2023年)

      1、资源内容地址:https://blog.csdn.net/2301_79696294/article/details/143733939 2、数据特点:今年全新,手工精心整理,放心引用,数据来自权威,且标注《数据来源》,相对于其他人的控制变量数据准确很多,适合写论文做实证用 ,不会出现数据造假问题 3、适用对象:大学生,本科生,研究生小白可用,容易上手!!! 4、课程引用: 经济学,地理学,城市规划与城市研究,公共政策与管理,社会学,商业与管理

      pillow-10.3.0-cp39-cp39-linux_armv7l.whl

      pillow-10.3.0-cp39-cp39-linux_armv7l.whl

      opencv_contrib_python-4.5.1.48-cp39-cp39-linux_armv7l.whl

      opencv_contrib_python-4.5.1.48-cp39-cp39-linux_armv7l.whl

    Global site tag (gtag.js) - Google Analytics