来自套接字的 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