隐锋的BLOG
ASP,.net开发
flash去开发应用,,免不了网络通讯,特别是网络游戏,需要用到即使通讯。
as3提供了两个支持即时通讯的类:XMLSocket和Socket,前者其实是只支持发送字符串,而后者就强大多了,支持发送字节,相对来说比较底层,而这也给我们更多的发挥空间。
其实,flash socket的网络底层接受数据,就以与C++服务器通讯为例子,C++服务器一般会发一段一段数据过来,每段数据都是由一定结构组成的,一般是消息头和消息头,然后再逐步分层解析。
在这里,我只说接受网络底层的处理,一般一段数据前面,还有有一个4个字节左右的数据,表示的是后面网络流里的数据有多少....
看下简单示意图
net1.jpg
我们网络底层需要做的处理,就是根据头4个字节判断出后面的数据大小,然后把那一整块取出来,抛给上层解析,然后又在不停地侦听,收到指定大小之后,又做类似的操作,下面看详细的代码
  1. /**
  2. * @(#)NetBottomHandle.as
  3. * @author soda.C  mail:sujun10@21cn.com
  4. * @version  1.0
  5. *
  6. Copyright (C), 2007 soda.C
  7. *
  8. This program is protected by copyright laws.
  9. *
  10. ;Program Name:GameHall
  11. * @data 2008-3-20
  12. */
  13. package org.sujun.net
  14. {
  15.     import flash.net.Socket;
  16.     import flash.events.ProgressEvent;
  17.     import flash.utils.ByteArray;
  18.     /**
  19.      * socket数据流里的底层处理,从这里接受到服务器的数据,满足条件后就会抛出需要的字节
  20.      * 对数据流的数据,不做任何处理
  21.      */
  22.     public class NetBottomHandle
  23.     {
  24.         private var socket        :Socket;        
  25.         private var listener    :Function;        //接受网络解析出来的数据
  26.         private var msgLen        :int;            //消息长度
  27.         private var msgLenMax    :int;            //收到的消息最大长度
  28.         private var headLen        :int;            //消息头长度
  29.         private var isReadHead    :Boolean;        //是否已经读了消息头
  30.         private var bytes        :ByteArray;        //所读数据的缓冲数据,读出的数据放在这里
  31.         
  32.         public function NetBottomHandle()
  33.         {
  34.             msgLenMax = 5000;    //5000字节
  35.             headLen = 4;        //4个字节
  36.             bytes = new ByteArray();
  37.             
  38.         }
  39.         /**
  40.          * 设置一个网络通讯实例
  41.          */  
  42.         public function setSocket(socket:Socket):void
  43.         {
  44.             this.socket = socket;
  45.             //监听......
  46.             socket.addEventListener(ProgressEvent.SOCKET_DATA, onServerData,false,0,true);
  47.         }
  48.         /**
  49.          * 接受在网络层里收到的原始数据,传递过来的数据为描述长度,以及ByteArray对象functon(len,bytes)
  50.          * @param listener:接受数据函数
  51.          */
  52.         public function receiverNetData(listener:Function):void
  53.         {
  54.             this.listener = listener;
  55.         }
  56.         /**
  57.          * 服务器发送过来的数据都在这里接收,最底层的
  58.          */
  59.         private function onServerData(event:ProgressEvent):void
  60.         {
  61.             //一有收到数据的事件,就通过这个函数进行检验
  62.             parseNetData();
  63.         }
  64.         /**
  65.          * 解析网络数据流
  66.          */
  67.         private function parseNetData():void
  68.         {
  69.             //如果需要读信息头
  70.             if(isReadHead)
  71.             {
  72.                 if(socket.bytesAvailable >= headLen)
  73.                 {
  74.                     //读出指示后面的数据有多大
  75.                     msgLen = socket.readUnsignedInt();
  76.                     isReadHead = false;
  77.                 }
  78.             }
  79.             //如果已经读了信息头,则看能不能收到满足条件的字节数
  80.             if(!isReadHead && msgLen <= msgLenMax)
  81.             {
  82.                 //如果为0,表示收到异常消息
  83.                 if(msgLen == 0)
  84.                 {
  85.                     //一般消息长度为0的话,表示与服务器出了错,或者即将被断开等,通知客户端,进行特别处理
  86.                     listener(msgLen,null);
  87.                     return ;
  88.                 }
  89.                 //数据流里的数据满足条件,开始读数据
  90.                 if(socket.bytesAvailable >= msgLen)
  91.                 {
  92.                     //指针回归
  93.                     bytes.position = 0;
  94.                     //取出指定长度的网络字节
  95.                     socket.readBytes(bytes, 0, msgLen);
  96.                     listener(msgLen,bytes);
  97.                 }
  98.             }
  99.             isReadHead = false;
  100.             //如果数据流里还满足读取数据条件,继续读取数据
  101.             if(socket.bytesAvailable >= headLen)
  102.             {
  103.                 parseNetData();
  104.             }
  105.         }
  106.     }
  107. }
复制代码
代码我就不详细解说了,注释得很清楚,这段代码也是经过我写过几个版本锤炼过的。呵呵
在实际应用中,表现也是比较稳定的
当然,这是比较早期的了,以后再正正应用中,可能还需要做更多的处理,例如每个网络字节的缓冲,缓存等,以免过多字节造成socket出错等等
希望有兴趣的人继续留贴讨论,呵呵
posted on 2009-12-05 18:29  糊涂隐锋  阅读(1010)  评论(1编辑  收藏  举报