圣叹@游戏开发

我们面对现实,我们终于理想

ByteArray in URLRequest, is it AMF3?

| |
23:18 , Qizhi
下面的代码十分困惑:

var re:URLRequest = new URLRequest("http://www.***.com");
re.method = URLRequestMethod.POST;

var byte:ByteArray = new ByteArray();
byte.writeUTF("hi");
byte.writeUTF("why");
byte.writeInt(1);

var obj:Object = {};
obj.a = 1;
obj.b = "hi";
byte.writeObject(obj);

re.data = byte;

var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.load(re);

按预测,URLRequest在post ByteArray数据时会按照其默认编码(AMF3)序列化,但事实情况是,只有代码中Object对应的字段被准确序列化,而int,String等值对象被序列化后掩码错误。上述代码抓包数据:
00 02 68 69 | 00 03 77 68 | 79 00 00 00 | 01 0A 0B 01 | 03 61 04 01 | 03 62 06 05 | 68 69 01

数据中的"|"为我加入的分格符号。可以看出,String被序列化后由长度+正文组成,但是掩码(marker)是文档中定义的undefined-marker(int的掩码也被错误的写为0x00),即0x00.唯独Object的掩码是正常的0x0A,并且其属性a与b的值的掩码是均是正确的0x04与0x06.
不解?...
网友评论(8):
Edison
Email
2010/05/02 00:00
讨论这个想解决什么样的问题?PS:这个BLOG能不能将回复反馈到电子邮箱呢?
jinni
Email Homepage
2010/04/16 15:32
看来你已经明白过来怎么回事了,我也就不多做解释了,我之前说不同的URLRequest不会用AMF编码的意思是你不能要求所有服务器都有解析AMF的能力,就像lite3说的,URLRequest完全不知道也不关心你用什么方式编码(当然,urlencoded它还是知道的)
lite3
Email Homepage
2010/04/14 10:33
其实URLRequest跟AMF没有任何关系的,URLRequest用二进制时仅仅是把传递的字节流,至于是否是AMF,它并不关心.
可以这样理解:URLRequest不知道AMF的存在,不管你要传递什么东西,我只是纯物理的传递过去,我不做任何检测或解析
OK,再说下ByteArray,ByteArray本身是操作字节的东西,也不管AMF,只是Adobe为了方便,多给了writeObject,readObject方法来方便的应用AMF协议
Qizhi 回复于 2010/04/14 15:10
ByteArray作为对象必然有其序列化为字节流的方法,AMF只是其中一种方法而已。关键在于其defaultObjectEncoding=AMF3属性很迷惑人。
Y.Boy
Email Homepage
2010/04/12 14:31
嘻嘻,我却在AS3语言参考里找到这个:

writeObject () 方法  
public function writeObject(object:*):void
语言版本:  ActionScript 3.0
运行时版本:  AIR 1.0, Flash Player 9

将对象以 AMF 序列化格式写入字节数组。
Qizhi 回复于 2010/04/12 14:49
看到了,看起来我理解错了。ByteArray在存储数据时只有object是使用AMF3的,从文档看,其它类型均是直接写入(writeUTF例外,用了16-bit的头来表明串长度)。
Y.Boy
Email Homepage
2010/04/12 11:06
我是这样认为的:
ByteArray in URLRequest,并没有做任何序列化工作。刚好你使用了采用AMF3协议的writeObject()方法。
我们可以自己实现对 AS3 对象序列化,而不使用AMF3。而摆在眼前的事实就是,你使用的writeObject()是采用AMF3的。而其它方法(writeUTF、writeInt...)只是纯粹地把数据写进 ByteArray 而不采用任何序列化协议。
.......
如果你想统一协议,你可以尝试这样做:

var byte:ByteArray = new ByteArray();
byte.writeObject("hi");
byte.writeObject("why");
byte.writeObject(1);

var obj:Object = {};
obj.a = 1;
obj.b = "hi";
byte.writeObject(obj);

就是统一用 writeObject() 方法。这样,全部都是AMF3了,而不会出现你的情况。
Qizhi 回复于 2010/04/12 14:46
无语。
Y.Boy
Email Homepage
2010/04/12 10:28
ByteArray都有写入基本数据类型的方法,但复杂数据类型只能通过 writeObject() 方法。就是,基本数据类型是值,复杂数据类型是引用。可以想一下,复杂数据类型可以用什么方法写进 ByteArray 呢?writeObject就是最好的选择。而writeObject就是采用AMF3序列化数据的。
Qizhi 回复于 2010/04/12 10:37
这样的协议是什么玩意?用大腿写出来的?序列化方式都不统一?
Y.Boy
Email Homepage
2010/04/12 10:21
不难理解的。
writeObject() 方法是按AMF3序列化的,而其它则都是纯字节。
通过HTTP传输ByteArray,可以实现上传的效果,我一直都这样来上传文件的。
jinni
Email Homepage
2010/04/12 09:41
普通的URL请求怎么会用AMF编码?如果用了服务器端怎么解析?FP只有在和支持AMF的服务器(如BlazeDS,AMFPHP)进行远程过程调用(RemoteObject)或消息传递的时候才会进行AMF编码。writeObject()本身是按AMF序列化的,其他都只是单纯转换成字节而已(UTF本身就有长度标示位)
Qizhi 回复于 2010/04/12 10:22
编码和服务端解析是两回事情。编码我可以使用字符串,也可以使用字节流,这无所谓,定义好协议,服务端用相同的协议解码即可,例如使用AMF3。RemoteObject也是HTTP调用,本质上和URLRequest没什么不同。单纯转换成字节也有很多种写法,关键在于URLRequest在序列化时值和引用类型为什么有差异(前者非AMF3而后者是)?
分页: 1/1 第一页 1 最后页
发表评论:

昵称: 
电邮:
网址: