来自套接字的 AS3 / AIR readObject() - 如何检查是不是已收到所有数据?

Posted

技术标签:

【中文标题】来自套接字的 AS3 / AIR readObject() - 如何检查是不是已收到所有数据?【英文标题】:AS3 / AIR readObject() from socket - How do you check all data has been received?来自套接字的 AS3 / AIR readObject() - 如何检查是否已收到所有数据? 【发布时间】:2011-11-12 19:09:59 【问题描述】:

如果你将一个简单的对象写入一个套接字:

var o:Object = new Object();
o.type = e.type;
o.params = e.params;
_socket.writeObject(o);
_socket.flush();

那么在客户端你就简单用了吗:

private function onData(e:ProgressEvent):void

    var o:Object = _clientSocket.readObject();

或者在调用.readObject()之前,您是否必须实施某种方法来检查是否已收到所有数据?

【问题讨论】:

【参考方案1】:

有两种方法:

如果您确信您的对象可以放入一个数据包中,您可以执行以下操作:

var fromServer:ByteArray = new ByteArray;

while( socket.bytesAvailable )
    socket.readBytes( fromServer );

fromServer.position = 0;
var myObj:* = fromServer.readObject();

如果您有可能拥有多个数据包消息,那么常见的用法是在消息前面加上消息的长度。类似(伪代码):

var fromServer:ByteArray    = new ByteArray();
var msgLen:int              = 0;

while ( socket.bytesAvailable > 0 )

    // if we don't have a message length, read it from the stream
    if ( msgLen == 0 )
        msgLen = socket.readInt();

    // if our message is too big for one push
    var toRead:int  = ( msgLen > socket.bytesAvailable ) ? socket.bytesAvailable : msgLen;
    msgLen          -= toRead; // msgLen will now be 0 if it's a full message

    // read the number of bytes that we want.
    // fromServer.length will be 0 if it's a new message, or if we're adding more
    // to a previous message, it'll be appended to the end
    socket.readBytes( fromServer, fromServer.length, toRead );

    // if we still have some message to come, just break
    if ( msgLen != 0 )
        break;

    // it's a full message, create your object, then clear fromServer

让您的套接字能够像这样读取意味着可以正确读取多个数据包消息,并且您不会错过几乎同时发送 2 条小消息的任何消息(因为第一条消息会处理它全部作为一条消息,因此缺少第二条)

【讨论】:

不是真的,因为我从未测试过它:) - 我必须实现这一点,因为我们有时可以快速收到消息(即 2 条小消息),我不想错过它们。一条消息经过多次通话很少(无论如何对我来说),但确实会发生。 Socket是基于TCP的,所以这可能会给你一个想法:***.com/questions/2613734/… 您可以做的另一件事是在发送之前压缩消息(使用zlib),然后在调用readObject()之前使用ByteArray.uncompress() 循环检查不起作用。即使使用循环调用,我在接收图像时也收到了多个 onData 调用。 它可以让您一次读取多个字节(即,如果您在一个数据包中有多条消息) - 如果您一次读取所有内容,那么您不需要while。如果您收到多个onData 调用您的图像,也许它是通过多个数据包进来的?【参考方案2】:

处理 TCP 时的规则 #1:它是八位字节流传输协议。您可能永远不会假设一次获得多少个八位位组(8 位长的值,通常称为字节),总是编写可以处理任何数量的代码,无论是太少还是太多。无法保证写入不会被拆分为多个读取。也不能保证单次读取将来自单次写入。

【讨论】:

【参考方案3】:

我处理它的方式是进行回调,服务器告诉客户端收到了空位。 空位附加到您要发送到服务器的数据字符串的末尾。

String.fromCharCode(0)

在你的情况下你也在做

_socket.writeObject(o);

你应该发送一个字符串而不是一个对象。 所以像这样。

_socket.writeUTFBytes( 'Hellow World" + String.fromCharCode(0) );

注意 ************ * 大多数第一次使用套接字创建者的一件事是 事实上,从客户端到服务器的第一个请求通过 套接字连接的端口是对 跨域策略.xml

【讨论】:

【参考方案4】:

如果您只想发送对象,最简单的解决方案是在每个对象之前发送一个 int(size)。发送确切的尺寸并不重要,您可以发送少一点。在我的例子中,我发送了一个位图数据,以及对象的宽度和高度。显然位图数据的大小是如此之大,如果您只发送它就可以了,而忽略其余的。

var toRead=0;
protected function onSocketData(event:ProgressEvent):void
                if(toRead==0) 
                toRead=socket.readInt() 
            
            if(socket.bytesAvailable>toRead)
                var recieved:Object=socket.readObject() 
                /*do stuff with recieved object*/
                toRead=0
            

【讨论】:

以上是关于来自套接字的 AS3 / AIR readObject() - 如何检查是不是已收到所有数据?的主要内容,如果未能解决你的问题,请参考以下文章

AS3:我的 AIR 应用程序应该使用啥 resolvePath?

适用于 Android 应用 (AS3) 的 Chromecast 和 Air

使用 WiFi Direct 或 Air/AS3 中的热点连接应用程序

AS3:如何激活android air app?

添加按钮以将图片保存到AIR或AS3中

使用 AS3 AIR 在移动设备上滚动?