3

我在尝试使用 ByteArrays 通过 Socket 发送对象和 unsigned int 时遇到了一个奇怪的问题。我正在尝试处理我可能会在多个数据包中接收数据的情况。

这是我的套接字数据处理程序:

protected function handleSocketData(e:ProgressEvent):void{
        var s:Socket = e.target as Socket;

        trace("pre if " + len + " " + s.bytesAvailable);
        if (len == 0 && s.bytesAvailable >= 4) {
            len = s.readUnsignedInt();

        }

        trace(len + " " + s.bytesAvailable);
        if (len > 0 && s.bytesAvailable >= len){
            var ba:ByteArray = new ByteArray();
            //s.readBytes(ba, 0, len);
            s.readBytes(ba, 0, s.bytesAvailable); //should be len

            //trace("handle socket before inflate " + ba.length);
            ba.inflate();
            //trace("handle socket after inflate " + ba.length);
            var o:Object = ba.readObject();
            Overlord.updatePlayers(o);
            trace(o.player);
            len = 0;


        }
}

问题在于s.readBytes(ba, 0, len);

我正在使用 len (在类范围内定义)来处理我可能会收到多个数据包的情况。现在这似乎在我一次通过套接字获取数据时起作用。

pre if 0 44 - trace I'm getting before the first if statement
38 40 - trace I'm getting after
frank - Everything comes in fine, working!

现在,如果我再次通过套接字发送数据:

**first send:**
pre if 0 44
38 40
frank - working, yay!
**things start to fail every send after:**
pre if 0 46
218759168 42
pre if 218759168 84
218759168 84
pre if 218759168 127
218759168 127

现在看来 readBytes 将数据留在缓冲区中。

奇怪的是,当我换掉s.readBytes(ba, 0, len);一切s.readBytes(ba, 0, s.bytesAvailable);似乎都有效时:

使用 s.readBytes(ba, 0, s.bytesAvailable);

**first send**
pre if 0 44
38 40
frank
**everything seems to work after, no old data in the buffer?**
pre if 0 44
38 40
frank
pre if 0 43
37 39
frank

使用的问题bytesAvailable是现在我无法处理多个数据包。

pre if 2214 2218
2214 2218
RangeError: Error #2006: The supplied index is out of bounds.
at flash.utils::ByteArray/readObject()

我不太确定我在这里缺少什么,似乎只有在我使用 socket.bytesAvailable 时缓冲区才会被清除。有人有意见吗?

编辑

我正在使用这种方法通过套接字发送数据。通过写入 ByteArray 的长度并在数据处理程序中读回它,我试图处理跨多个数据包获取数据对象。

        public function sendData(socketData:*):void{
        if(_connected){
            //trace("sending");
            var ba:ByteArray = new ByteArray();
            ba.writeObject(socketData);
            ba.position = 0;
            //trace("byteArray len before send and defalte: " + ba.length)
            ba.deflate();
            //trace("byteArray len before send and after defalte: " + ba.length)
            socket.writeUnsignedInt(ba.length);
            socket.writeBytes(ba, 0, ba.length);
            socket.flush();
        } else {
            throw new Error("Socket not open");
        }
    }
4

1 回答 1

0

您应该真正将数据从套接字中拉出到一个字节数组中,然后对字节数组而不是套接字进行操作。当您在套接字或字节数组上调用任何 read***() 方法时,您会将 .position 属性移动到您的 read 方法的值。这也是您在 readObject 上收到提供的索引错误的原因。在调用 readObject 之前,先将 BA 的 .position 属性设置为 0。

 ba.position = 0;
 var o:Object = ba.readObject();

我对您的问题的评论以及我认为此答案中的详细信息至少是您的代码的一个基本问题。您还应该发布发送套接字的代码,以便我们更容易解决这个问题。

于 2012-04-29T06:32:41.833 回答