[AS3]BaseSocket类-可以提升Socket数据传输效率
需要Flash Player 9.0或更高版本的支持
原理就是结合AMF3和ByteArray的特性对原来数据进行压缩后再传输,这样就可以大大提高数据传输效率。
我现在把客户端方法进行优化,现在写成一个BaseSocket类来方便调用。
BaseSocket类
- /**
- * @author Kinglong
- * @link kinglong@gmail.com
- * @builddate 20081121
- * @flashplayerversion 9+
- * @version 0.1
- */
- package com.klstudio.socket {
- import flash.events.*;
- import flash.net.Socket;
- import flash.net.ObjectEncoding;
- import flash.system.Security;
- import flash.utils.ByteArray;
- public class BaseSocket extends EventDispatcher{
- private var _host:String;
- private var _port:uint;
- private var _socket:Socket;
- public function BaseSocket(host:String, port:uint = 80 ) {
- this ._host = host;
- this ._port = port;
- this ._socket = new Socket();
- this ._socket.objectEncoding = ObjectEncoding.AMF3;
- Security.loadPolicyFile("xmlsocket://" + this .host + ":" + this .port);
- this ._socket.addEventListener(Event.CONNECT, handler);
- this ._socket.addEventListener(Event.CLOSE, handler);
- this ._socket.addEventListener(IOErrorEvent.IO_ERROR, handler);
- this ._socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handler);
- this ._socket.addEventListener(ProgressEvent.SOCKET_DATA, handler);
- }
- public function get host():String {
- return _host;
- }
- public function get port():uint {
- return _port;
- }
- public function get connected():Boolean {
- return this ._socket.connected;
- }
- public function connect(): void {
- this ._socket.connect(host, port);
- }
- public function close(): void {
- this ._socket.close();
- }
- public function send(params:Object= null ): void {
- if (! this .connected || params == null ){
- return ;
- }
- var bytes:ByteArray = new ByteArray();
- bytes.writeObject(params);
- bytes.compress();
- this ._socket.writeBytes(bytes);
- this ._socket.flush();
- this .dispatchEvent( new BaseSocketEvent(BaseSocketEvent.SENDING, params));
- }
- private function received(): void {
- var bytes:ByteArray = new ByteArray();
- while ( this ._socket.bytesAvailable > 0 ) {
- this ._socket.readBytes(bytes, 0 , this ._socket.bytesAvailable);
- }
- try {
- bytes.uncompress();
- this .dispatchEvent( new BaseSocketEvent(BaseSocketEvent.RECEIVED, bytes.readObject()));
- }catch (error:Error) {
- this .dispatchEvent( new BaseSocketEvent(BaseSocketEvent.DECODE_ERROR));
- }
- }
- private function handler(event:Event): void {
- switch (event.type) {
- case Event.CLOSE:
- this .dispatchEvent( new BaseSocketEvent(BaseSocketEvent.CLOSE));
- break ;
- case Event.CONNECT:
- case IOErrorEvent.IO_ERROR:
- case SecurityErrorEvent.SECURITY_ERROR:
- this .dispatchEvent( new BaseSocketEvent(event.type));
- break ;
- case ProgressEvent.SOCKET_DATA:
- this .received();
- break ;
- }
- }
- }
- }
/** * @author Kinglong * @link kinglong@gmail.com * @builddate 20081121 * @flashplayerversion 9+ * @version 0.1 */ package com.klstudio.socket { import flash.events.*; import flash.net.Socket; import flash.net.ObjectEncoding; import flash.system.Security; import flash.utils.ByteArray; public class BaseSocket extends EventDispatcher{ private var _host:String; private var _port:uint; private var _socket:Socket; public function BaseSocket(host:String, port:uint = 80) { this._host = host; this._port = port; this._socket = new Socket(); this._socket.objectEncoding = ObjectEncoding.AMF3; Security.loadPolicyFile("xmlsocket://" + this.host + ":" + this.port); this._socket.addEventListener(Event.CONNECT, handler); this._socket.addEventListener(Event.CLOSE, handler); this._socket.addEventListener(IOErrorEvent.IO_ERROR, handler); this._socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handler); this._socket.addEventListener(ProgressEvent.SOCKET_DATA, handler); } public function get host():String { return _host; } public function get port():uint { return _port; } public function get connected():Boolean { return this._socket.connected; } public function connect():void { this._socket.connect(host, port); } public function close():void { this._socket.close(); } public function send(params:Object=null):void { if(!this.connected || params == null){ return; } var bytes:ByteArray = new ByteArray(); bytes.writeObject(params); bytes.compress(); this._socket.writeBytes(bytes); this._socket.flush(); this.dispatchEvent(new BaseSocketEvent(BaseSocketEvent.SENDING, params)); } private function received():void { var bytes:ByteArray = new ByteArray(); while (this._socket.bytesAvailable > 0) { this._socket.readBytes(bytes, 0, this._socket.bytesAvailable); } try{ bytes.uncompress(); this.dispatchEvent(new BaseSocketEvent(BaseSocketEvent.RECEIVED, bytes.readObject())); }catch (error:Error) { this.dispatchEvent(new BaseSocketEvent(BaseSocketEvent.DECODE_ERROR)); } } private function handler(event:Event):void { switch(event.type) { case Event.CLOSE: this.dispatchEvent(new BaseSocketEvent(BaseSocketEvent.CLOSE)); break; case Event.CONNECT: case IOErrorEvent.IO_ERROR: case SecurityErrorEvent.SECURITY_ERROR: this.dispatchEvent(new BaseSocketEvent(event.type)); break; case ProgressEvent.SOCKET_DATA: this.received(); break; } } } }
BaseSocketEvent类
- /**
- * @author Kinglong
- * @link kinglong@gmail.com
- * @builddate 20081121
- * @flashplayerversion 9+
- * @version 0.1
- */
- package com.klstudio.socket {
- import flash.events.*;
- public class BaseSocketEvent extends Event {
- public static const SECURITY_ERROR:String = SecurityErrorEvent.SECURITY_ERROR;
- public static const IO_ERROR:String = IOErrorEvent.IO_ERROR;
- public static const DECODE_ERROR:String = "decode_error" ;
- public static const RECEIVED:String = "received" ;
- public static const SENDING:String = "sending" ;
- public static const CLOSE:String = Event.CLOSE;
- public static const CONNECT:String = Event.CONNECT;
- private var _data:Object;
- public function BaseSocketEvent(type:String, data:Object = null ) {
- super (type, true );
- this ._data = data;
- }
- public function get data():Object {
- return _data;
- }
- override public function toString():String {
- return formatToString( "BaseSocketEvent" , "type" , "bubbles" , "cancelable" , "data" );
- }
- override public function clone():Event {
- return new BaseSocketEvent(type, data);
- }
- }
- }
/** * @author Kinglong * @link kinglong@gmail.com * @builddate 20081121 * @flashplayerversion 9+ * @version 0.1 */ package com.klstudio.socket { import flash.events.*; public class BaseSocketEvent extends Event { public static const SECURITY_ERROR:String = SecurityErrorEvent.SECURITY_ERROR; public static const IO_ERROR:String = IOErrorEvent.IO_ERROR; public static const DECODE_ERROR:String = "decode_error"; public static const RECEIVED:String = "received"; public static const SENDING:String = "sending"; public static const CLOSE:String = Event.CLOSE; public static const CONNECT:String = Event.CONNECT; private var _data:Object; public function BaseSocketEvent(type:String, data:Object = null) { super(type, true); this._data = data; } public function get data():Object { return _data; } override public function toString():String { return formatToString("BaseSocketEvent", "type", "bubbles", "cancelable", "data"); } override public function clone():Event { return new BaseSocketEvent(type, data); } } }
调用实例
- /**
- * ...
- * @author Kinglong
- * @version 0.1
- */
- package project.test {
- import flash.display.*;
- import flash.events.*;
- import flash.text.TextField;
- import com.klstudio.data.Map;
- import com.klstudio.socket.BaseSocket;
- import com.klstudio.socket.BaseSocketEvent;
- public class TestGame extends Sprite {
- private var _socket:BaseSocket;
- private var _id:uint;
- private var _lists:Map;
- private var _info:TextField;
- public function TestGame() {
- _info = new TextField();
- _info.selectable = false ;
- _info.text = "未连接" ;
- addChild(_info);
- stage.addEventListener(MouseEvent.MOUSE_UP, stageHandler);
- _lists = new Map();
- _socket = new BaseSocket( "localhost" , 110 );
- configureListeners(_socket);
- _socket.connect();
- }
- private function configureListeners(dispatcher:IEventDispatcher): void {
- dispatcher.addEventListener(BaseSocketEvent.CLOSE, handler);
- dispatcher.addEventListener(BaseSocketEvent.CONNECT, handler);
- dispatcher.addEventListener(BaseSocketEvent.IO_ERROR, handler);
- dispatcher.addEventListener(BaseSocketEvent.SECURITY_ERROR, handler);
- dispatcher.addEventListener(BaseSocketEvent.SENDING, handler);
- dispatcher.addEventListener(BaseSocketEvent.RECEIVED, handler);
- dispatcher.addEventListener(BaseSocketEvent.DECODE_ERROR, handler);
- }
- private function handler(event:BaseSocketEvent): void {
- switch (event.type) {
- case BaseSocketEvent.RECEIVED:
- receive(event.data);
- break ;
- case BaseSocketEvent.CLOSE:
- debug("连接关闭" );
- removeAll();
- break ;
- case BaseSocketEvent.CONNECT:
- debug("连接中..." );
- _socket.send( { event:"init" } );
- break ;
- case BaseSocketEvent.IO_ERROR:
- case BaseSocketEvent.SECURITY_ERROR:
- debug("连接失败" );
- break ;
- case BaseSocketEvent.DECODE_ERROR:
- debug("解码失败" );
- break ;
- }
- }
- private function stageHandler(event:MouseEvent): void {
- _socket.send( { event:"move" , x: this .mouseX, y: this .mouseY } );
- }
- private function receive(object:Object): void {
- switch (object.event) {
- case "init" :
- init(object.id);
- for (var i:uint = 0 ; i < object.list.length; i++ ) {
- var item:Object = object.list[i];
- add(item.id, item.x, item.y);
- }
- break ;
- case "move" :
- move(object.id, object.x, object.y);
- break ;
- case "remove" :
- remove(object.id);
- break ;
- case "add" :
- add(object.id);
- break ;
- }
- }
- private function init(id:uint): void {
- this ._id = id;
- add(id);
- }
- private function add(id:uint, x:Number = undefined, y:Number = undefined): void {
- x = x || stage.stageWidth / 2 ;
- y = y || stage.stageHeight / 2 ;
- if (_lists.containsKey(id)) {
- return ;
- }
- var role:GameRole = new GameRole(id,_id == id);
- role.move(x,y);
- addChild(role);
- _lists.put(id, role);
- }
- private function move(id:uint, x:Number, y:Number): void {
- if (_lists.containsKey(id)) {
- var role:GameRole = _lists.get(id);
- role.to(x, y);
- }
- }
- private function remove(id:uint): void {
- if (_lists.containsKey(id)) {
- var role:GameRole = _lists.remove(id);
- trace(role);
- if ( this .contains(role)) {
- removeChild(role);
- }
- role = null ;
- }
- }
- private function removeAll(): void {
- var keys:Array = _lists.keys;
- for (var i:uint = 0 ; i < keys.length; i++ ) {
- var role:GameRole = _lists.remove(keys[i]);
- if ( this .contains(role)) {
- removeChild(role);
- }
- role = null ;
- }
- }
- private function debug(msg:String): void {
- _info.text = msg;
- trace(msg);
- }
- }
- }
/** * ... * @author Kinglong * @version 0.1 */ package project.test { import flash.display.*; import flash.events.*; import flash.text.TextField; import com.klstudio.data.Map; import com.klstudio.socket.BaseSocket; import com.klstudio.socket.BaseSocketEvent; public class TestGame extends Sprite { private var _socket:BaseSocket; private var _id:uint; private var _lists:Map; private var _info:TextField; public function TestGame() { _info = new TextField(); _info.selectable = false; _info.text = "未连接"; addChild(_info); stage.addEventListener(MouseEvent.MOUSE_UP, stageHandler); _lists = new Map(); _socket = new BaseSocket("localhost", 110); configureListeners(_socket); _socket.connect(); } private function configureListeners(dispatcher:IEventDispatcher):void { dispatcher.addEventListener(BaseSocketEvent.CLOSE, handler); dispatcher.addEventListener(BaseSocketEvent.CONNECT, handler); dispatcher.addEventListener(BaseSocketEvent.IO_ERROR, handler); dispatcher.addEventListener(BaseSocketEvent.SECURITY_ERROR, handler); dispatcher.addEventListener(BaseSocketEvent.SENDING, handler); dispatcher.addEventListener(BaseSocketEvent.RECEIVED, handler); dispatcher.addEventListener(BaseSocketEvent.DECODE_ERROR, handler); } private function handler(event:BaseSocketEvent):void { switch(event.type) { case BaseSocketEvent.RECEIVED: receive(event.data); break; case BaseSocketEvent.CLOSE: debug("连接关闭"); removeAll(); break; case BaseSocketEvent.CONNECT: debug("连接中..."); _socket.send( { event:"init" } ); break; case BaseSocketEvent.IO_ERROR: case BaseSocketEvent.SECURITY_ERROR: debug("连接失败"); break; case BaseSocketEvent.DECODE_ERROR: debug("解码失败"); break; } } private function stageHandler(event:MouseEvent):void { _socket.send( { event:"move", x:this.mouseX, y:this.mouseY } ); } private function receive(object:Object):void { switch(object.event) { case "init": init(object.id); for (var i:uint = 0; i < object.list.length; i++ ) { var item:Object = object.list[i]; add(item.id, item.x, item.y); } break; case "move": move(object.id, object.x, object.y); break; case "remove": remove(object.id); break; case "add": add(object.id); break; } } private function init(id:uint):void { this._id = id; add(id); } private function add(id:uint, x:Number = undefined, y:Number = undefined):void { x = x || stage.stageWidth / 2; y = y || stage.stageHeight / 2; if (_lists.containsKey(id)) { return; } var role:GameRole = new GameRole(id,_id == id); role.move(x,y); addChild(role); _lists.put(id, role); } private function move(id:uint, x:Number, y:Number):void { if (_lists.containsKey(id)) { var role:GameRole = _lists.get(id); role.to(x, y); } } private function remove(id:uint):void { if (_lists.containsKey(id)) { var role:GameRole = _lists.remove(id); trace(role); if (this.contains(role)) { removeChild(role); } role = null; } } private function removeAll():void { var keys:Array = _lists.keys; for (var i:uint = 0; i < keys.length; i++ ) { var role:GameRole = _lists.remove(keys[i]); if (this.contains(role)) { removeChild(role); } role = null; } } private function debug(msg:String):void { _info.text = msg; trace(msg); } } }