这个类是对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的,肯定还会碰到很多怪怪问题,比如数据不对,拿出来的数据有问题,还要进行分段处理什么的

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类源代码:

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 事件类源代码

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);
    }
  }
}
[最后修改由 sunbright, 于 2008-06-26 20:53:19]
评论Feed 评论Feed: http://www.xiaos8.com/feed.asp?q=comment&id=105
怎么一页才显示这么点文章?点快速检索查看更多的文章: 显示全部 | 评论: 10 | 排序 | 观看的: 9930
socket*
[ 2008-08-11 14:26:02 ]
初步接触socket,能给个实例看看么
比如send ("test","say{haha}");
这个怎么来获取并显示出类似:test say{haha}

如果有时间的话把每个type的例子都写个看看 好彻底领悟!多谢多谢!

sunbright
[ 2008-08-11 14:33:42 ]
你侦听SOCKET_DATA事件,然后trace出来看看就知道了啊。。
其实flash客户端socket编程很简单的。。多trace一下数据就明白了
socket*
[ 2008-08-11 14:52:00 ]
那个我了解了,只要e.data["sunbright"]就可以了,问下
可不可以传递类似一个或多个这样{key:"key",value:"value"}的对象;
以及如何获取其中的属性?
send({...},{...}.{...})并且获得每个object中的对应的一些属性
sunbright
[ 2008-08-11 14:53:52 ]
可能当然是可能但是需要你自己做解析
socket*
[ 2008-08-11 14:55:00 ]
这个能给个例子看看么?
sunbright
[ 2008-08-11 15:30:57 ]
这个得你自己摸索了。。这不是一句话讲的清除的。。另外这个类已经很老了,过时了,这个类的设计就我看来,较差劲
socket*
[ 2008-08-11 15:48:52 ]
- -,对于新手我觉得还不错啊,难道有比这更先进的类设计,能否展示一下看看。
sunbright
[ 2008-08-11 17:52:28 ]
有空会重写这个类的,新手的确可以先学学这个拉。。。
我也是从这个基础学过来的。。。
socket*
[ 2008-08-12 15:16:32 ]
呵呵,关注中。
问下,能不能通过socket服务器发送图片或是swf,然后在flash客户端解析出相应的图片或swf?
有个聊天功能:图片+文字的混合模式 像qq那种一般是怎么实现的?
sunbright
[ 2008-08-12 15:22:26 ]
第一个问题:可以,但是需要编码解码方面的一些知识,应该不难,没试过,但理论是没问题的
第二个问题:可以实现,但比较难,要做很多协调性的工作等
简单的方法可以用TextField的htmlText属性实现
复杂的,自己继承Sprite写一个,那就比较复杂了。。

发表
表情图标
[表情01] [表情02] [表情03] [表情04] [表情05] [表情06] [表情07] [表情08] [表情09] [表情10] [表情11] [表情12] [表情13] [表情14] [表情15] [表情16] [表情17] [表情18] [表情19] [表情20] [表情21] [表情22] [表情23] [表情24]
UBB代码
转换链接
表情图标
悄悄话
昵称:   验证码: *
 
快速浏览
类别
标题
评论/流量
日期