未知的 AMF 类型和将文件从 flash 传输到 java 时出现其他错误
我正在使用 Flash 工具将数据传输到 Java。我在一次发送多个对象时遇到问题。发送的对象只是通用的对象对象,因此不需要注册类别名或任何内容。
发送一个对象效果很好。一旦我开始发送多个对象(将相同的对象放入数组中并发送),它就开始变得奇怪。数组中最多三个对象似乎工作正常。不仅如此,我在 readObject() 函数中遇到了不同的错误,例如:
- Unknown AMF type '47'
- Unknown AMF type '40'
- Unknown AMF type '20'
- OutOfBoundsExceptions index 23, size 0
- NullPointerException
- 等发送
3 个对象会起作用,发送 4 个对象会出现错误。如果我删除前 3 个有效的之一(同时保留添加的第四个),它将再次工作。有人知道发生了什么事吗?
更多信息:
- 通信通过 Flash 端的 Socket 类进行。这是纯AS3,没有flex。
- 消息在发送之前被压缩并在服务器上解压缩,所以我很确定这不是缓冲区大小问题(除非我遗漏了一些东西)
- BlazeDS 版本似乎是 jar 上的 4.0.0.14931
- Flash 版本是 10.1(它是AIR 应用程序)
使用粗略代码更新
发送的对象示例:
var o:Object = { };
o._key = this._key.toString();
o.someParam = someString;
o.someParam2 = someInt;
o.someParam3 = [someString1, someString2, someString3];
...
它被添加到我们的事件对象(我们用它来确定要调用的事件、数据等) 经过)。事件对象被注册为类别名
该对象通过 Socket 发送到服务器,如下所示:
myByteArray.writeObject( eventObj );
myByteArray.compress();
mySocket.writeBytes( myByteArray );
mySocket.flush();
在服务器端,我们接收字节并解压缩它们。我们创建一个 Amf3Input 对象并设置输入流,然后读取它:
Amf3Input amf3Input = new Amf3Input( mySerializationContext );
amf3Input.setInputStream( new ByteArrayInputStream( buffer ) ); // buffer is a byte[]
MyEventObj eventObj = (MyEventObj)amf3Input.readObject(); // MyEventObj is the server version of the client event object
如果它将因“未知 AMF 类型错误”而崩溃,它会立即执行此操作,即当我们尝试读取该对象时,而不是当它尝试读取子对象。
在逐步执行读取代码时,似乎当我传递一个对象数组时,如果长度 <= 4,它会正确读取长度。如果长度大于该长度,则读取长度为 4。
I'm using a Flash tool to transfer data to Java. I'm having problems when it comes to sending multiple objects at once. The objects being sent are just generic Object objects, so it's not a case of needed to register a class alias or anything.
Sending one object works fine. Once I start sending multiple objects (putting the same Objects in an Array and sending that), it starts getting weird. Up to three objects in an Array seems to work fine. More than that I get different errors in the readObject()
function, such as:
- Unknown AMF type '47'
- Unknown AMF type '40'
- Unknown AMF type '20'
- OutOfBoundsExceptions index 23, size 0
- NullPointerException
- etc.
Sending 3 objects will work, sending 4 gives me the error. If I delete one of the previous 3 that worked (while keeping the fourth that was added), it'll work again. Anyone know what's going on?
Some more info:
- Communication goes through a Socket class on the Flash side. This is pure AS3, no flex.
- Messages are compressed before being sent and decompressed on the server, so I'm pretty sure it's not a buffer size issue (unless I'm missing something)
- BlazeDS version seems to be 4.0.0.14931 on the jar
- Flash version is 10.1 (it's an AIR app)
Update with rough code
Examples of the objects being sent:
var o:Object = { };
o._key = this._key.toString();
o.someParam = someString;
o.someParam2 = someInt;
o.someParam3 = [someString1, someString2, someString3];
...
It's added to our event object (which we use to determine the event to call, the data etc to pass). The event object is been registered as a class alias
That object is sent to the server through a Socket like so:
myByteArray.writeObject( eventObj );
myByteArray.compress();
mySocket.writeBytes( myByteArray );
mySocket.flush();
On the server side, we receive the bytes, and decompress them. We create a Amf3Input object and set the input stream, then read it:
Amf3Input amf3Input = new Amf3Input( mySerializationContext );
amf3Input.setInputStream( new ByteArrayInputStream( buffer ) ); // buffer is a byte[]
MyEventObj eventObj = (MyEventObj)amf3Input.readObject(); // MyEventObj is the server version of the client event object
If it's going to crash with an "unknown AMF type error", it does so immediately i.e. when we try to read the object, and not when it's trying to read a subobject.
In stepping through the read code, it seems when I pass an array of objects, if the length is <= 4, it reads the length right. If the length is bigger than that, it reads it's length as 4.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您遇到 AMF 反序列化错误,则可能有多种问题导致该问题。以下是进行进一步诊断的几种技术:
使用网络流量嗅探器来确保您发送的内容与您接收的内容匹配。在 Mac 上,我将使用 CocoaPacketAnalyzer,或者您也可以尝试 Charles,它实际上可以解码它注意到的 AMF 数据包。
将数据提供给不同的 AMF 库,例如 PyAMF 或 RocketAMF 查看是否是 BlazeDS 的问题或您调用它的方式的问题。您也可能会收到不同的错误消息,这将使您更好地了解故障所在。
检查AMF数据包的格式。 AMF 服务器调用有一些额外的包装,如果反序列化器不希望遇到这种包装,则会抛出该包装,对于纯序列化对象反之亦然。服务器调用数据包始终以
0x00
开头,后跟 AMF 版本(0x00
、0x03
,或在极少数情况下0x02< /code>).
If you're getting AMF deserialization errors, there are several possible issues that could be contributing to the problem. Here are several techniques for doing further diagnostics:
Use a network traffic sniffer to make sure that what you are sending matches what you are receiving. On the Mac I'll use CocoaPacketAnalyzer, or you can try Charles, which can actually decode AMF packets that it notices.
Feed the data to a different AMF library, like PyAMF or RocketAMF to see if it's a problem with BlazeDS or with how you're calling it. It's also possible that you may get a different error message that will give you a better idea of where it's failing.
Check the format of the AMF packet. AMF server calls have some additional wrapping around them that would throw off a deserializer if it's not expecting to encounter that wrapping, and vice versa for purely serialized objects. Server call packets always start off with a
0x00
, followed by the AMF version (0x00
,0x03
, or in rare cases0x02
).好的,我找到了问题所在。基本上消息在发送之前被压缩并在服务器上解压缩。我没有看到消息解压缩到的
byte[]
缓冲区始终是 1024 长度,这对于小型对象数组来说很好。然而,一旦通过,它就会覆盖缓冲区(我不太确定当你尝试写入比可用字节更多的字节时,Java 中会发生什么 - 无论是循环还是移动数据)。当读取 amf 对象时,它首先读取一个 int,并使用它来确定它尝试解码的对象类型。由于这个 int 是乱码(47, 110, -10),所以它失败了。
我想是时候开始预先考虑消息长度了:)
感谢您的帮助。
Ok, I figured out the problem. Basically messages are compressed before being sent and decompressed on the server. What I didn't see was that the
byte[]
buffer that the message was being decompressed to was always 1024 length, which was fine for small arrays of objects. Once that was passed however, it would overwrite the buffer (I'm not quite sure what happens in Java when you try to write more bytes than are available - whether it loops back around, or shifts the data).When it came to reading the amf object, the first thing it does it read an int, and uses this to determine what type of object it's trying to decode. As this int was gibberish (47, 110, -10), it was failing.
Time to start prepending message lengths I think :)
Thanks for the help.