当前位置: 首页 > 图文教程 > Flash动画 > ActionScript > Flash AS3教程:ApplySocket类

ActionScript
FLASH 3D相册之利用BitmapData类制作
Flash 脚本游戏开发教程 第一课
Flash 脚本游戏开发教程第二课
Flash 脚本游戏开发教程第三课
Flash 脚本游戏开发教程第四课
Flash 脚本游戏开发教程第五课
Flash 脚本游戏开发教程第六课
Flash 脚本游戏开发教程第七课
Flash 脚本游戏开发教程第八课
Flash AS实现的蝌蚪摆尾动画的教程
从基础开始深入学Flash AS3教程(4)(译文)
从基础开始深入学Flash AS3教程(5)(译文)
从基础开始深入Flash AS3教程(2)(译文)
从基础开始深入学Flash AS3教程(3)(译文)
Flash AS3对单个图片进行角色动作化处理
从基础开始深入Flash AS3教程(1)(译文)
Flash教程:if条件语句的用法
Flash AS教程:_visible属性的详细讲解
Flash AS教程:图片环绕旋转效
Flash教程:trace()的使用

ActionScript 中的 Flash AS3教程:ApplySocket类


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-16   浏览: 102 ::
收藏到网摘: n/a

前面学习了Flash AS3教程:运算符,今天学习的ApplySocket类,这个类是对socket应用就行了系统化封装,并且考虑了很多因素,整合出来的一套,较为完善的flash程序部分socket解决方案
比如:一些socket服务端,不一定你send过去一条,他马上就会转发,可能会有延时,或者数据堆在一起等现象,而有写socket服务端,在发送数据的时候,会有一些附加码等,这样不利于取出真实数据
该类除了普通的用法,就是对上述假设情况整合了一套解决方案,虽不是很完善,但是能解决大部分问题,至少我碰到过的问题,用这个类应该可以轻松搞定,并且可以适合更复杂的

另外光看讲解,可能不大懂,提供了什么解决方案,来解决上面这些问题,因此,麻烦大家赖着性子,先过一到代码,然后在看后面的用法

index.base.net.ApplySocket类:
对socket进行封装,并且提供多种socket解决方案

构造函数:
public function ApplySocket(_isSide:Boolean = false,_datatype:String = "String")
第一参数,是否使用包边,对数据进行处理,详细请看isSide属性
第二参数,默认数据发布类型
如果构造函数中两个参数都是用默认值,则该类只是一个普普通通的socket类

connect方法:
public function connect(_host:String,_port:int):void
连接远程socket服务端
第一参数:主机地址,可以是202.89.***.***,或者www.*****.com这样的
第二参数:连接的端口号

send方法:
public function send(...strs):void
发送数据到socket服务端
如果datatype为Object或者ArrayObject的时候,send方法传入的参数必须大于或者等于两个!否则会引发错误!

close方法:
public function close():void
关闭与远程服务端连接

connect事件:
当连接上了之后,会调度该事件

close事件:
当socket关闭后,会调度该事件

sync事件:
当有数据需要同步的时候,会调度该事件

error事件:
当连接失败的时候,会调度该事件

静态常量:
public static const ARRAY:String = "Array";
public static const STRING:String = "String";
public static const OBJECT:String = "Object";
public static const ARRAY_ARRAY:String = "ArrayArray";
public static const ARRAY_OBJECT:String = "ArrayObject";
分别表示datatype的5种类型

host属性:
public var host:String;
当connect后,会自动把主机地址记录到该值上

port属性:
public var port:int;
当connect后,会自动把连接端口号记录到该值上

space属性:
public var space:String = " ";
当send传入2个或者2个以上参数时,采用何种值进行隔开,默认是 空格,如果将值改为"",则表示不用间隔进行隔开

ls属性:
public var ls:String = "{";
当isSide为true的时候,放在左边所使用的记号

rs属性:
public var rs:String = "}";
当isSide为true的时候,放在右边所使用的记号

connected属性:
public var connected:Boolean;
返回socket是否已连接上

isSide属性:
public var isSide:Boolean;
是否加上包边处理
如果该值为true,则表示,send传入的参数都将会用rs和ls包起来进行传输到socket端,当socket原版返回数据的时候,在使用正则将真正的数据取出来,并且以datatype类型返回
反之,则不做任何处理。

datatype属性:
public var datatype:String;
发布同步事件的时候,data采用何种类型返回
String:以字符串返回,就是说传入什么返回什么

Array:以数组返回,选择使用Array返回的时候,isSide值必须为true,否则无法断点找出数组,原理就是,通过使用ls rs两个符号包起来,然后使用正则把符号中的数据提取出来,并且返回数组。如果,socket服务端,可能还会抛出其他数据给客户端,那么采用isSide包边处理,则socket回传的数据,该类会自动处理,将send出去的数据原本拿下来,回传数据不受影响

Object:以Object返回,如果send过去的数据,都是以一个变量名一个参数值来传输的,那么可以采用Object来接收数据,这样的话,返回data中,直接返回send进去的第一个参数,即可获得值(该类型不常用,一般只在特殊情况使用)

ArrayArray:以数组嵌套数组的形式返回数据,如果socket的执行效率不是很高,或者同步要求不是很高,那么客户端send一次,未必会接收到同步事件,可能会堆积在一起,一起发送到客户端,这个时候,就可以采用ArrayArray的形式,那么该类会帮你把send过去的数据,重新划分,并且以一个数组为一个send数据的形式返回,很利于做连连看,对对碰类似同步不是很即时,很多个动作可以堆积到一起来发送

ArrayObject:以数组嵌套Object的形式返回数据,不过多说,只不过是Array加上Object的符合模式而已(该类型也不常用)

Object与ArrayObject,很适合用在群聊天室,比如send("sunbright","大家好{哈 哈}");那么即时你在说话的内容加了很多怪怪符号,比如加上分隔符,空格等等,因为Object的解析原理是,拿出第一个参数做为引用变量名,然后把后面的所有数据赋值给这个引用变量名来返回,所有后面的数据不管怎么样,都是不会破坏数据内容,即得到data数据后只要返回data的sunbright值,即可得到说话内容,不会因为格式错误,而把说话的内容有所改变

该类的作用在datatype属性中,讲了很多东西
下面讲讲应用:
该类的关键就在于isSide和datatype两个值,
如果isSide为true,那么就等于启用了数据包边处理,那么当你调用send方法传入某些参数,只要socket方做到的是,传进去什么他返回给你什么,那么通过同步事件,又会自动把处理过的数据,拿出来,做到数据的准确性,不会因为传了很多参数,有时候会紊乱。

而当datatype的属性改变后:
返回给你的数据,就做了一些处理,这样程序拿到最终数据的时候,根本不用处理,就可以直接使用,因为该类已经把需要解决的问题,搞定了
比如数据类型是ArrayArray的时候,请看下面的例子:
下面是一个同步的例子,接收到的数据类型是ArrayArray,拿到数据之后for循环一下,把该放的数据,放到相应位置,则完成同步。程序大大简化了,不会我们拿到数据了还要处理,如果是第一次玩socket的,肯定还会碰到很多怪怪问题,比如数据不对,拿出来的数据有问题,还要进行分段处理什么的

CODE:
private function syncFun(e:ApplySocketEvent):void{
    var tmpAr:Array = e.data as Array;
    for(var i:int = 0; i < tmpAr.length; i   ){
        var ar:Array = tmpAr[i];
        var _index:String = ar[1];
        if(_index != index && (has(_index) || ar[0] == "create")){
            switch(ar[0]){
                case "create":
                    createTank(_index);
                break;
                case "move":
                    var moveStr:String = ar[2];
                    var moveAr:Array = moveStr.split("");
                    get(_index).move(expBoo(moveAr[0]),expBoo(moveAr[1]),expBoo(moveAr[2]),expBoo(moveAr[3]));
                    moveAr = null;
                break;
                case "bullet":
                    get(_index).bullet();
                break;
                case "shell":
                    get(_index).shell();
                break;
                case "turn":
                    var turnStr:String = ar[2];
                    var turnAr:Array = turnStr.split("");
                    get(_index).turn(expBoo(turnAr[0]),expBoo(turnAr[1]));
                break;
            }
        }
        ar = null;
    }
    tmpAr = null;
}
如果没看懂,还有虾米问题,就跟贴吧。。。


ApplySocket类源代码:

CODE:
package index.base.net{
   
    import flash.events.EventDispatcher;
    import flash.events.ProgressEvent;
    import flash.events.IOErrorEvent;
    import flash.events.Event;
    import flash.net.Socket;
   
    import index.base.events.ApplySocketEvent;
   
    public class ApplySocket extends EventDispatcher{
        
        private var socket:Socket;
        
        public static const ARRAY:String = "Array";
        public static const STRING:String = "String";
        public static const OBJECT:String = "Object";
        public static const ARRAY_ARRAY:String = "ArrayArray";
        public static const ARRAY_OBJECT:String = "ArrayObject";
        
        public var host:String;
        public var port:int;
        public var space:String = " ";
        public var ls:String = "{";
        public var rs:String = "}";
        public var isSide:Boolean;
        public var datatype:String;
        public var connected:Boolean = false;
        
        public function ApplySocket(_isSide:Boolean = false,_datatype:String = "String"){
            isSide = _isSide;
            datatype = _datatype;
        }
        
        //连接
        public function connect(_host:String,_port:int):void{
            host = _host;
            port = _port;
            
            if(connected) socket.close();
            socket = new Socket;
            socket.connect(host,port);
            socket.addEventListener(IOErrorEvent.IO_ERROR,errorFun);
            socket.addEventListener(Event.CONNECT,connectFun);
        }
        
        //发送
        public function send(...strs):void{
            if(datatype == OBJECT || datatype == ARRAY_OBJECT){
                if(strs.length < 2) throw new Error("当数据类型等于Object或者ArrayObject的时候,send方法传入参数必须两个或者两个以上!");
            }
            
            var str:String = "";
            for(var i:int = 0; i < strs.length; i   ){
                str  = strs[i];
                if(i != strs.length - 1) str  = space;
            }
            if(isSide) str = ls   str   rs;
            socket.writeUTFBytes(str);
            socket.flush();
        }
        
        //断开
        public function close():void{
            clearEvent();
            connected = false;
            socket.close();
            socket = null;
        }
        
        //连接事件
        private function connectFun(e:Event):void{
            connected = true;
            clearEvent();
            socket.addEventListener(ProgressEvent.SOCKET_DATA,socketDataFun);
            socket.addEventListener(Event.CLOSE,closeFun);
            dispatchEvent(new ApplySocketEvent(ApplySocketEvent.CONNECT));
        }
        
        //关闭事件
        private function closeFun(e:Event):void{
            connected = false;
            dispatchEvent(new ApplySocketEvent(ApplySocketEvent.CLOSE));
        }
        
        //失败事件
        private function errorFun(e:IOErrorEvent):void{
            close();
            dispatchEvent(new ApplySocketEvent(ApplySocketEvent.ERROR));
        }
        
        //接收事件
        private function socketDataFun(e:ProgressEvent):void{
            var i:int;
            var tmp:Object = socket.readUTFBytes(socket.bytesAvailable);
            if(isSide){
                tmp = tmp.match(new RegExp("\\"   ls   "[^\\"   rs   "]*\\"   rs,"g"));
                for(i = 0; i < tmp.length; i   ){
                    var str:String = tmp[i];
                    tmp[i] = str.substr(1,str.length - 2);
                }
            }
            
            switch(datatype){
                case STRING:
                    if(tmp is Array) tmp = tmp.join("");
                break;
                case ARRAY:
                    if(tmp is String) throw new Error("错误!如果数据类型选择Array,那么isSide必须为true!");
                break;
                case OBJECT:
                    if(tmp is Array) throw new Error("错误!如果数据类型选择Object,那么isSide必须为false!");
                    tmp = change(tmp as String);
                break;
                case ARRAY_OBJECT:
                    if(tmp is String) throw new Error("错误!如果数据类型选择ArrayObject,那么isSide必须为true!");
                    for(i = 0; i < tmp.length; i   ) tmp[i] = change(tmp[i]);
                break;
                case ARRAY_ARRAY:
                    if(tmp is String) throw new Error("错误!如果数据类型选择ArrayArray,那么isSide必须为true!");
                    for(i = 0; i < tmp.length; i   ) tmp[i] = tmp[i].split(space);
                break;
            }
            
            var eve:ApplySocketEvent = new ApplySocketEvent(ApplySocketEvent.SYNC);
            eve.data = tmp;
            dispatchEvent(eve);
            
            tmp = null;
            eve = null;
        }
        
        //清理事件侦听
        private function clearEvent():void{
            if(socket != null){
                if(socket.hasEventListener(IOErrorEvent.IO_ERROR)) socket.removeEventListener(IOErrorEvent.IO_ERROR,errorFun);
                if(socket.hasEventListener(Event.CONNECT)) socket.removeEventListener(Event.CONNECT,connectFun);
                if(socket.hasEventListener(ProgressEvent.SOCKET_DATA)) socket.removeEventListener(ProgressEvent.SOCKET_DATA,socketDataFun);
                if(socket.hasEventListener(Event.CLOSE)) socket.removeEventListener(Event.CLOSE,closeFun);
            }
        }
        
        //转换Object
        private function change(tmp:String):Object{
            var tmpAr:Array = tmp.split(space);
            var obj:Object = new Object;
            obj[tmpAr.shift()] = tmpAr.join(space);
            tmpAr = null;
            return obj;
        }
    }
}
ApplySocketEvent 事件类源代码

CODE:
package index.base.events{
   
    import flash.events.Event;
   
    public class ApplySocketEvent extends Event{
        
        public static const CONNECT:String = "connect";
        public static const CLOSE:String = "close";
        public static const SYNC:String = "sync";
        public static const ERROR:String = "error";
        
        public var data:Object;
        
        public function ApplySocketEvent(type:String){
            super(type);
        }
    }
}