Flex的sdk中已经有Socket类,虽然用起来比较方便,但真正的项目用起来未免有些繁琐了,所以我们有必要对其进行必要的改造下,让Socket更灵敏,更好用!
Flex的Socket可以向其写入Object,本次的工具着重完成写入Object,并且读取SocketServer返回的Object!
1.创建class,SocketTool
public class SocketTool{}
2.为SocketTool添加socket:Socket属性并注册好一些默认的事件监听,将来就靠此属性来完成通信任务!
添加bytes:ByteArray属性,用于将来解压从服务器获取到的字节,之后将解压后的字节读取为Object
再次添加2个状态属性,
_usable,辨别socket是否可以用,
_status,存放socket的状态信息
public class SocketTool{private var socket:Socket = new Socket();private var bytes:ByteArray;private var byteArrayTool:ByteArrayTool = new ByteArrayTool();private var _usable:Boolean = false;private var _statusInfo:String = "状态未知";public function SocketTool(host:String,port:uint){socket.connect(host,port);socket.addEventListener(Event.CLOSE,onClose);socket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);socket.addEventListener(Event.CONNECT,onConn);socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);socket.addEventListener(IOErrorEvent.IO_ERROR,onIoError);}
//默认 事件private function onClose(e:Event){usable = false;statusInfo = "Socket关闭";trace("Socket Already Closed");}private function onSocketData(e:ProgressEvent){if(socket.bytesAvailable){var r:String = socket.readMultiByte(socket.bytesAvailable,"gbk");usable=true;statusInfo = "Socket可用";trace("Receive Server's Data"+r);}}private function onConn(e:Event){trace("Socket connect complete");statusInfo = "获取安全信息,Socket不可用";sendTestInfo();function sendTestInfo(){socket.writeMultiByte("<policy-file-request/>","gbk");socket.flush();}}private function onSecurityError(e:SecurityErrorEvent){usable = false;statusInfo = "安全错误,Socket不可用";trace("SecurityError,check Server's [Cross Domain]");}private function onIoError(e:IOErrorEvent){usable = false;statusInfo = "io错误,Socket不可用";trace("IoError");}//----public function get statusInfo():String{return _statusInfo;}public function set statusInfo(_statusInfo:String){this._statusInfo = _statusInfo;}public function get usable():Boolean{return _usable;}public function set usable(_usable:Boolean):void{this._usable = _usable;}//关闭事件public function addCloseEvent(closeHandler:Function):void{removeCloseEvent(closeHandler);socket.addEventListener(Event.CLOSE,closeHandler);}public function removeCloseEvent(closeHandler:Function):void{socket.removeEventListener(Event.CLOSE,closeHandler);}//连接ok事件public function addConnectEvent(connHandler:Function):void{removeConnectEvent(connHandler);socket.addEventListener(Event.CONNECT,connHandler);}public function removeConnectEvent(closeHandler:Function):void{socket.removeEventListener(Event.CONNECT,closeHandler);}//安全失败事件public function addSecurityErrorEvent(securityHandler:Function):void{removeSecurityErrorEvent(securityHandler);socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityHandler);}public function removeSecurityErrorEvent(securityHandler:Function):void{socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,securityHandler);}//io errorpublic function addIoErrorEvent(ioHandler:Function):void{removeIoErrorEvent(ioHandler);socket.addEventListener(IOErrorEvent.IO_ERROR,ioHandler);}public function removeIoErrorEvent(ioHandler:Function):void{socket.removeEventListener(IOErrorEvent.IO_ERROR,ioHandler);}//收到 数据事件public function addSocketDataEvent(socketDataHandler:Function):void{var timer:Timer = new Timer(400);timer.addEventListener(TimerEvent.TIMER,circle);timer.start();function circle(e:TimerEvent){if(usable){removeSocketDataEvent(onSocketData); //移除默认事件socket.addEventListener(ProgressEvent.SOCKET_DATA,socketDataHandler);statusInfo = "Socket已可用";timer.stop();timer.removeEventListener(TimerEvent.TIMER,circle);}}}public function removeSocketDataEvent(socketDataHandler:Function):void{socket.removeEventListener(ProgressEvent.SOCKET_DATA,socketDataHandler);}
//添加上connect方法,便于将来再次连接服务器
//连接服务器public function connect(host:String,port:uint){socket.connect(host,port);}
ok,到目前为止,初始化的任务完成,重要的方法就要开始.
任务1.让socket发送Object,如果服务器响应了,触发某个回调
/*** 通过回调方式完成一次发送与接收* @send:要发送的对象* @compress:是否要将发送对象压缩* @receiverHandler: 接收的回调* */public function sendAndReceive(send:Object,receiverHandler:Function,compress:Boolean=false):void{var timer:Timer = new Timer(400);timer.addEventListener(TimerEvent.TIMER,circle);timer.start();function circle(e:TimerEvent){if(usable){writeObject(send,compress);addSocketDataEvent(receiverHandler);timer.stop();timer.removeEventListener(TimerEvent.TIMER,circle);}}}
任务2.让socket发送Object,如果服务器响应了,触发回调,并且将服务器返回的Object放入回调
/*** 通过回调方式完成一次发送对象与接收对象* @send:要发送的对象* @compress:是否要将发送对象压缩* @receiverObjectHandler: 接收对象的回调* */public function sendAndReceiverObject(send:Object,receiverObjectHandler:Function,compress:Boolean=false):void{var timeout:Boolean = true;var time:uint = 0;var timer:Timer = new Timer(400);timer.addEventListener(TimerEvent.TIMER,circle);timer.start();var timer2:Timer = new Timer(1000);timer.addEventListener(TimerEvent.TIMER,timeoutCircle);function circle(e:TimerEvent){if(usable){writeObject(send,compress);addSocketDataEvent(receive);timer.stop();timer.removeEventListener(TimerEvent.TIMER,circle);}}function timeoutCircle(e:TimerEvent){if(!timeout || time >6){//完毕timer2.stop();timer2.removeEventListener(TimerEvent.TIMER,timeoutCircle);}if(timeout){time ++;}if(time > 6){Main.statusItem = new ObjectProxy({name:'服务器响应超时'});}else{Main.statusItem = new ObjectProxy({name:'数据获取时间:'+time});}}function receive(e:ProgressEvent){timeout = false;var resp:Object = readObject(true);receiverObjectHandler(resp);removeSocketDataEvent(receive);}}
ok,到此今天的任务就完成了,我们利用socket的writeObject,readObject方法与服务器进行通信,用socket以amf3完成Object方式完成通信!
以下是此类的完成代码
=======================================================================
类.SocketTool
package org.sk.tools{import flash.events.Event;import flash.events.IOErrorEvent;import flash.events.ProgressEvent;import flash.events.SecurityErrorEvent;import flash.events.TimerEvent;import flash.net.Socket;import flash.utils.ByteArray;import flash.utils.Timer;import mx.utils.ObjectProxy;/*** Socket工具* */public class SocketTool{private var socket:Socket = new Socket();private var bytes:ByteArray;private var byteArrayTool:ByteArrayTool = new ByteArrayTool();private var _usable:Boolean = false;private var _statusInfo:String = "状态未知";public function SocketTool(host:String,port:uint){socket.connect(host,port);socket.addEventListener(Event.CLOSE,onClose);socket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);socket.addEventListener(Event.CONNECT,onConn);socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError);socket.addEventListener(IOErrorEvent.IO_ERROR,onIoError);}//默认 事件private function onClose(e:Event){usable = false;statusInfo = "Socket关闭";trace("Socket Already Closed");}private function onSocketData(e:ProgressEvent){if(socket.bytesAvailable){var r:String = socket.readMultiByte(socket.bytesAvailable,"gbk");usable=true;statusInfo = "Socket可用";trace("Receive Server's Data"+r);}}private function onConn(e:Event){trace("Socket connect complete");statusInfo = "获取安全信息,Socket不可用";sendTestInfo();function sendTestInfo(){socket.writeMultiByte("<policy-file-request/>","gbk");socket.flush();}}private function onSecurityError(e:SecurityErrorEvent){usable = false;statusInfo = "安全错误,Socket不可用";trace("SecurityError,check Server's [Cross Domain]");}private function onIoError(e:IOErrorEvent){usable = false;statusInfo = "io错误,Socket不可用";trace("IoError");}//----public function get statusInfo():String{return _statusInfo;}public function set statusInfo(_statusInfo:String){this._statusInfo = _statusInfo;}public function get usable():Boolean{return _usable;}public function set usable(_usable:Boolean):void{this._usable = _usable;}//关闭事件public function addCloseEvent(closeHandler:Function):void{removeCloseEvent(closeHandler);socket.addEventListener(Event.CLOSE,closeHandler);}public function removeCloseEvent(closeHandler:Function):void{socket.removeEventListener(Event.CLOSE,closeHandler);}//连接ok事件public function addConnectEvent(connHandler:Function):void{removeConnectEvent(connHandler);socket.addEventListener(Event.CONNECT,connHandler);}public function removeConnectEvent(closeHandler:Function):void{socket.removeEventListener(Event.CONNECT,closeHandler);}//安全失败事件public function addSecurityErrorEvent(securityHandler:Function):void{removeSecurityErrorEvent(securityHandler);socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityHandler);}public function removeSecurityErrorEvent(securityHandler:Function):void{socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,securityHandler);}//io errorpublic function addIoErrorEvent(ioHandler:Function):void{removeIoErrorEvent(ioHandler);socket.addEventListener(IOErrorEvent.IO_ERROR,ioHandler);}public function removeIoErrorEvent(ioHandler:Function):void{socket.removeEventListener(IOErrorEvent.IO_ERROR,ioHandler);}//收到 数据事件public function addSocketDataEvent(socketDataHandler:Function):void{var timer:Timer = new Timer(400);timer.addEventListener(TimerEvent.TIMER,circle);timer.start();function circle(e:TimerEvent){if(usable){removeSocketDataEvent(onSocketData); //移除默认事件socket.addEventListener(ProgressEvent.SOCKET_DATA,socketDataHandler);statusInfo = "Socket已可用";timer.stop();timer.removeEventListener(TimerEvent.TIMER,circle);}}}public function removeSocketDataEvent(socketDataHandler:Function):void{socket.removeEventListener(ProgressEvent.SOCKET_DATA,socketDataHandler);}//连接服务器public function connect(host:String,port:uint){socket.connect(host,port);}/*** 通过回调方式完成一次发送与接收* @send:要发送的对象* @compress:是否要将发送对象压缩* @receiverHandler: 接收的回调* */public function sendAndReceive(send:Object,receiverHandler:Function,compress:Boolean=false):void{var timer:Timer = new Timer(400);timer.addEventListener(TimerEvent.TIMER,circle);timer.start();function circle(e:TimerEvent){if(usable){writeObject(send,compress);addSocketDataEvent(receiverHandler);timer.stop();timer.removeEventListener(TimerEvent.TIMER,circle);}}}/*** 通过回调方式完成一次发送对象与接收对象* @send:要发送的对象* @compress:是否要将发送对象压缩* @receiverObjectHandler: 接收对象的回调* */public function sendAndReceiverObject(send:Object,receiverObjectHandler:Function,compress:Boolean=false):void{var timeout:Boolean = true;var time:uint = 0;var timer:Timer = new Timer(400);timer.addEventListener(TimerEvent.TIMER,circle);timer.start();var timer2:Timer = new Timer(1000);timer.addEventListener(TimerEvent.TIMER,timeoutCircle);function circle(e:TimerEvent){if(usable){writeObject(send,compress);addSocketDataEvent(receive);timer.stop();timer.removeEventListener(TimerEvent.TIMER,circle);}}function timeoutCircle(e:TimerEvent){if(!timeout || time >6){//完毕timer2.stop();timer2.removeEventListener(TimerEvent.TIMER,timeoutCircle);}if(timeout){time ++;}if(time > 6){Main.statusItem = new ObjectProxy({name:'服务器响应超时'});}else{Main.statusItem = new ObjectProxy({name:'数据获取时间:'+time});}}function receive(e:ProgressEvent){timeout = false;var resp:Object = readObject(true);receiverObjectHandler(resp);removeSocketDataEvent(receive);}}/*** 从Socket中读取压缩对象* @uncompress:是否解压* */private function readObject(uncompress:Boolean=false):Object{if(socket.bytesAvailable){bytes = new ByteArray();socket.readBytes(bytes,0,socket.bytesAvailable);try{if(uncompress){bytes.uncompress();}var obj:Object = bytes.readObject();return obj;}catch(e){var str:String = bytes.readMultiByte(socket.bytesAvailable,'gbk');trace(str);}}return null;}/*** 向Socket中写入对象* @compress:是否需要压缩* */private function writeObject(obj:Object,compress:Boolean=false):void{var timer:Timer = new Timer(400);timer.addEventListener(TimerEvent.TIMER,circle);timer.start();function circle(e:TimerEvent){if(usable){bytes = new ByteArray();bytes.writeObject(obj);if(compress)bytes.compress();socket.writeBytes(bytes,0,bytes.length);socket.flush();timer.stop();timer.removeEventListener(TimerEvent.TIMER,circle);}}}/*** 自动分段 传递对象* @obj:as对象* @compress:是否压缩* @size:每段字节个数* */public function writeParticalObjectAuto(obj:Object,compress:Boolean=false,size:uint=1){if(socket){bytes = new ByteArray();bytes.writeObject(obj);if(compress)bytes.compress();arr = byteArrayTool.split(bytes,size);if(arr){socket.removeEventListener(ProgressEvent.SOCKET_DATA,onSocketData);socket.addEventListener(ProgressEvent.SOCKET_DATA,autoReceive);autoSend(); //开始发送}}var index:uint = 0; //当前的位置索引var arr:Array;//自动发送function autoSend(){var o:ByteArray = arr[index];//生成 部分对象var part:Object ={};part.partical = o;part.pos = index;part.len = arr.length;writeObject(part);}//自动接收function autoReceive(e:ProgressEvent){if(socket.bytesAvailable){var obj:Object = readObject(true);if(obj.next == "next"){index ++;autoSend();}else if(obj.next == "done"){socket.removeEventListener(ProgressEvent.SOCKET_DATA,autoReceive);socket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);trace("对象序列全部发送完毕");}}}}
}}
2.类 ByteArrayTool
package org.sk.tools{import flash.utils.ByteArray;/** 字节数组工具*/public class ByteArrayTool{public function ByteArrayTool(){}/*** 将ByteArray拆分成若干段ByteArray,存入数组* @bytes : ByteArray* @size : 每组的最多的字节个数* */public function split(bytes:ByteArray,size:uint=1):Array{var arr:Array = [];if(bytes.length < size){arr.push(bytes);return arr;}var len:uint = bytes.length / size;var remain:uint = bytes.length % size;for(var i:uint = 0;i < len; i++){var tmp:ByteArray = new ByteArray();tmp.writeBytes(bytes,i*size,size);arr.push(tmp);}if(remain > 0){var tmp:ByteArray = new ByteArray();tmp.writeBytes(bytes,len * size ,remain);arr.push(tmp);}return arr;}/*** @size : size 组* */public function split2(bytes:ByteArray,groupSize:uint):Array{var arr:Array = [];var count:uint = bytes.length / groupSize; //每组的字节数var remain:uint = bytes.length % groupSize;for(var i:uint = 0;i<groupSize;i++){var tmp:ByteArray = new ByteArray();tmp.writeBytes(bytes,i*groupSize,count);if(i == (groupSize-1)){if(remain > 0){tmp.writeBytes(bytes,groupSize * count,remain);}}arr.push(tmp);}return arr;}}}
相关资源:谷歌安装器(如果Go安装器无法打卡可以使用这个)