【问题标题】: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()之前,您是否必须实施某种方法来检查是否已收到所有数据?

【问题讨论】:

    标签: actionscript-3 sockets


    【解决方案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的,所以这可能会给你一个想法:stackoverflow.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
                    }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-07-07
          • 1970-01-01
          • 2014-02-15
          • 1970-01-01
          • 2020-07-14
          • 1970-01-01
          • 2012-09-06
          • 2010-10-23
          相关资源
          最近更新 更多