最近项目需要做了一个UDP文件传输的例子,客户端与客户端的P2P连接需要服务器的协助,这里就没贴代码了。让人很郁闷的是FLEX中没有办法操作多线程,在网上找了一些例子好像都是用Timer实现的伪多线程,一方面TCP SOCKET 实现不了P2P,另一方面UDP SOCKET没有异步传输真叫人很头痛,期待Adobe可以开放更多的操作了
ObjectA.as代码
package com.UDP
{
import com.UDP.UDPEvent;
import flash.display.Sprite;
import flash.events.DatagramSocketDataEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.InvokeEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.net.DatagramSocket;
import flash.net.Socket;
import flash.net.registerClassAlias;
import flash.utils.ByteArray;
/**
* E2即时通UDP文件传输发起方
*/
public class ObjectA extends EventDispatcher
{
private var _sock:DatagramSocket;
private var _toip:String;
private var _toport:uint;
//数据包大小,1024bytes
private const _packsize:uint = 1019;
private var _packnum:uint = 0;
private var data:ByteArray= new ByteArray();
/**
* obj发送对象,sock本机socket,toip对方IP,toport对方端口
*/
public function ObjectA(sock:DatagramSocket,toip:String,toport:int)
{
_toip = toip;
_toport = toport;
_sock = sock;
_sock.addEventListener(DatagramSocketDataEvent.DATA,dataReceive);
_sock.receive();
}
/**
* 格式化传输数据并告知B要开始传输,命令头为1
*/
public function invokeB(obj:Object):void{
data.writeObject(obj);
//重置数据读取流,注意读取操作并不改变data所包含内容
data.position = 0;
trace(data.bytesAvailable);
_packnum = data.bytesAvailable/_packsize;
if(data.bytesAvailable%_packsize>0){
_packnum++;
}
var buffer:ByteArray = new ByteArray();
buffer.writeByte(1);
buffer.writeUnsignedInt(_packnum);
buffer.position = 0;
_sock.send(buffer,0,buffer.bytesAvailable,_toip,_toport);
}
/**
* 控制通道SOCKET接收数据事件处理
*/
private function dataReceive(e:DatagramSocketDataEvent):void{
var cmd:int = e.data.readByte();
var ret:ByteArray = new ByteArray();
switch(cmd){
case 1: //接受传输文件请求
transferOnce();
break;
case 2:
var buffer:ByteArray = new ByteArray();
while(e.data.bytesAvailable){
var packnum:uint = e.data.readUnsignedInt();
//reset package position and read length
this.data.position = (packnum*_packsize);
var vlen:uint = _packsize;
if(packnum==_packnum){
vlen = this.data.bytesAvailable;
}
//写入数据命令头0
buffer.writeByte(0);
//写入长度为packnum的包头
buffer.writeUnsignedInt(packnum);
//写入长度为vlen的包内容
var n:int = 0;
for(var j:uint=0;j<vlen;j++){
n = this.data.readByte();
buffer.writeByte(n);
}
//send package to client B
buffer.position = 0;
_sock.send(buffer,0,buffer.bytesAvailable,_toip,_toport);
buffer.clear();
}
//发送成功,发送结束标志,命令头为2
buffer.writeByte(2);
buffer.position = 0;
_sock.send(buffer,0,buffer.bytesAvailable,_toip,_toport);
break;
case 3:
this.dispatchEvent(new UDPEvent(UDPEvent.Complete));
this.finalize();
break;
default:
break;
}
}
/**
* 分片传输所有数据包,命令头为0
*/
private function transferOnce():void{
var buffer:ByteArray = new ByteArray();
var i:int = 0;
var n:int = 0;
while(this.data.bytesAvailable){
i++;
var vlen:uint = _packsize;
if(vlen>this.data.bytesAvailable){
vlen = data.bytesAvailable;
}
//写入数据命令头0
buffer.writeByte(0);
//写入长度为i的包头
buffer.writeUnsignedInt(i);
//写入长度为vlen的包内容
for(var j:uint=0;j<vlen;j++){
n = this.data.readByte();
buffer.writeByte(n);
}
var udpevent:UDPEvent = new UDPEvent(UDPEvent.Process,i/_packnum);
this.dispatchEvent(udpevent);
buffer.position = 0;
_sock.send(buffer,0,buffer.bytesAvailable,_toip,_toport);
buffer.clear();
}
//发送成功,发送结束标志,命令头为2
buffer.writeByte(2);
buffer.position = 0;
_sock.send(buffer,0,buffer.bytesAvailable,_toip,_toport);
}
/**
* 释放资源
*/
private function finalize():void{
this._packnum=0;
this.data.clear();
}
}
}