先看我遇到的问题,有个项目需要通过Socket传输大文件,在SDK4.6之前,因为AS3没有对于Socket写缓冲区的监听事件,也没有描述写缓冲区剩余空间的属性,所以只能以很慢的速度写入数据,如果写入过快就会导致数据包丢失,比如FlexFTP,就是通过Timer,每400毫秒写一次数据,这也算一种解决方式,4.6之前我也是这样做的,但是4.6之后Socket添加了一个bytesPending属性和一个OutputProgressEvent.OUTPUT_PROGRESS事件,可以报告写缓冲区中还剩余多少数据没有写到网络中,因此可以通过这个事件来加快传输速度,以下是我的代码:
private function onOutPutProgress(event:OutputProgressEvent):void{ if(event.bytesPending == 0){ if(fileStream.bytesAvailable > 0){ if(fileStream.bytesAvailable <= 4096){ trace(byteArray.position, byteArray.length); fileStream.readBytes(byteArray, 0, fileStream.bytesAvailable); trace("结束"); trace(byteArray.bytesAvailable); }else{ fileStream.readBytes(byteArray, 0, 4096); } byteSended += byteArray.bytesAvailable; clientSocket.writeBytes(byteArray, 0, byteArray.bytesAvailable); clientSocket.flush(); byteArray.clear(); }else{ fileStream.close(); clientSocket.close(); } }
}
使用这个事件后,发送速度提高了很多,但是遇到一个问题,我是通过FileStream打开一个文件,然后不断读取这个文件的剩余字节,这里需要用到ByteArray,每次用完,ByteArray都要clear一下,主要是重置position和length
这里我们先看一下官方的文档
意思是clear之后position和length都清零,IDE中鼠标移上去还有一段额外的文字:“显式的调用将清除ByteArray实例所占用的内存空间”。但是实际使用用却发现了一个问题,调用clear之后,ByteArray的长度没有变化,这直接导致最后一次写入时,由于文件的剩余字节数小于4096,但是在写到Socket时还是使用4096写入,所以接收端接收到的文件会稍微大一些,因为这里用的是4096,用户会发现文件大小始终与文件的占用空间一样大。解决办法是在下一次使用前显式调用ByteArray.length = 0。代码如下:
byteArray.length = 0; fileStream.readBytes(byteArray, 0, fileStream.bytesAvailable);