您的位置:首页 > 其它

Flash Socket 底层接受数据的初级处理(as3.0)

2010-09-29 16:15 337 查看
用flash去开发应用,,免不了网络通讯,特别是网络游戏,需要用到即使通讯。
as3提供了两个支持即时通讯的类:XMLSocket和Socket,前者其实是只支持发送字符串,而后者就强大多了,支持发送字节,相对来说比较底
层,而这也给我们更多的发挥空间。
其实,flash socket的网络底层接受数据,就以与C++服务器通讯为例子,C++服务器一般会发一段一段数据过来,每段数据都是由一定结构组成
的,一般是消息头和消息头,然后再逐步分层解析。
在这里,我只说接受网络底层的处理,一般一段数据前面,还有有一个4个字节左右的数据,表示的是后面网络流里的数据有多少.... 看下简单示意图



我们网络底层需要做的处理,就是根据头4个字节判断出后面的数据大小,然后把那一整块取出来,抛给上层解析,然后又在不停地侦听,收到指定大小之后,又做类似的操作,下面看详细的代码

/**

* @(#)NetBottomHandle.as

* @author soda.C mail:sujun10@21cn.com

* @version 1.0

* <br>Copyright (C), 2007 soda.C

* <br>This program is protected by copyright laws.

* <br>Program Name:GameHall

* @data 2008-3-20

*/

package
org.sujun.net

{

import
flash.net.Socket;

import
flash.events.ProgressEvent;

import
flash.utils.ByteArray;

/**

* socket数据流里的底层处理,从这里接受到服务器的数据,满足条件后就会抛出需要的字节

* 对数据流的数据,不做任何处理

*/

public
class
NetBottomHandle

{

private
var
socket :Socket;

private
var
listener :Function; //接受网络解析出来的数据

private
var
msgLen :int
; //消息长度

private
var
msgLenMax :int
; //收到的消息最大长度

private
var
headLen :int
; //消息头长度

private
var
isReadHead :Boolean; //是否已经读了消息头

private
var
bytes :ByteArray; //所读数据的缓冲数据,读出的数据放在这里

public
function
NetBottomHandle()

{

msgLenMax = 5000; //5000字节

headLen = 4; //4个字节

bytes = new
ByteArray();

}

/**

* 设置一个网络通讯实例

*/

public
function
setSocket(socket:Socket):void

{

this
.socket = socket;

//监听......

socket.addEventListener(ProgressEvent.SOCKET_DATA, onServerData,false
,0,true
);

}

/**

* 接受在网络层里收到的原始数据,传递过来的数据为描述长度,以及ByteArray对象functon(len,bytes)

* @param listener:接受数据函数

*/

public
function
receiverNetData(listener:Function):void

{

this
.listener = listener;

}

/**

* 服务器发送过来的数据都在这里接收,最底层的

*/

private
function
onServerData(event:ProgressEvent):void

{

//一有收到数据的事件,就通过这个函数进行检验

parseNetData();

}

/**

* 解析网络数据流

*/

private
function
parseNetData():void

{

//如果需要读信息头

if
(isReadHead)

{

if
(socket.bytesAvailable >= headLen)

{

//读出指示后面的数据有多大

msgLen = socket.readUnsignedInt();

isReadHead = false
;

}

}

//如果已经读了信息头,则看能不能收到满足条件的字节数

if
(!isReadHead && msgLen <= msgLenMax)

{

//如果为0,表示收到异常消息

if
(msgLen == 0)

{

//一般消息长度为0的话,表示与服务器出了错,或者即将被断开等,通知客户端,进行特别处理

listener(msgLen,null
);

return
;

}

//数据流里的数据满足条件,开始读数据

if
(socket.bytesAvailable >= msgLen)

{

//指针回归

bytes.position = 0;

//取出指定长度的网络字节

socket.readBytes(bytes, 0, msgLen);

listener(msgLen,bytes);

}

}

isReadHead = false
;

//如果数据流里还满足读取数据条件,继续读取数据

if
(socket.bytesAvailable >= headLen)

{

parseNetData();

}

}

}

}

/**   * @(#)NetBottomHandle.as   * @author soda.C  mail:sujun10@21cn.com   * @version  1.0   * <br>Copyright (C), 2007 soda.C   * <br>This program is protected by copyright laws.   * <br>Program Name:GameHall   * @data 2008-3-20   */  package org.sujun.net   {      import flash.net.Socket;      import flash.events.ProgressEvent;      import flash.utils.ByteArray;      /**       * socket数据流里的底层处理,从这里接受到服务器的数据,满足条件后就会抛出需要的字节       * 对数据流的数据,不做任何处理       */      public class NetBottomHandle       {          private var socket        :Socket;                  private var listener    :Function;        //接受网络解析出来的数据          private var msgLen        :int;            //消息长度          private var msgLenMax    :int;            //收到的消息最大长度          private var headLen        :int;            //消息头长度          private var isReadHead    :Boolean;        //是否已经读了消息头          private var bytes        :ByteArray;        //所读数据的缓冲数据,读出的数据放在这里                    public function NetBottomHandle()          {              msgLenMax = 5000;    //5000字节              headLen = 4;        //4个字节              bytes = new ByteArray();                        }          /**           * 设置一个网络通讯实例           */            public function setSocket(socket:Socket):void          {              this.socket = socket;              //监听......              socket.addEventListener(ProgressEvent.SOCKET_DATA, onServerData,false,0,true);                                      }          /**           * 接受在网络层里收到的原始数据,传递过来的数据为描述长度,以及ByteArray对象functon(len,bytes)           * @param listener:接受数据函数           */          public function receiverNetData(listener:Function):void          {              this.listener = listener;          }          /**           * 服务器发送过来的数据都在这里接收,最底层的           */          private function onServerData(event:ProgressEvent):void          {              //一有收到数据的事件,就通过这个函数进行检验              parseNetData();          }          /**           * 解析网络数据流           */          private function parseNetData():void          {              //如果需要读信息头              if(isReadHead)              {                  if(socket.bytesAvailable >= headLen)                  {                      //读出指示后面的数据有多大                      msgLen = socket.readUnsignedInt();                      isReadHead = false;                  }              }              //如果已经读了信息头,则看能不能收到满足条件的字节数              if(!isReadHead && msgLen <= msgLenMax)              {                  //如果为0,表示收到异常消息                  if(msgLen == 0)                  {                      //一般消息长度为0的话,表示与服务器出了错,或者即将被断开等,通知客户端,进行特别处理                      listener(msgLen,null);                      return ;                  }                  //数据流里的数据满足条件,开始读数据                  if(socket.bytesAvailable >= msgLen)                  {                      //指针回归                      bytes.position = 0;                      //取出指定长度的网络字节                      socket.readBytes(bytes, 0, msgLen);                      listener(msgLen,bytes);                  }              }              isReadHead = false;              //如果数据流里还满足读取数据条件,继续读取数据              if(socket.bytesAvailable >= headLen)              {                  parseNetData();              }          }      }  }


代码我就不详细解说了,注释得很清楚,这段代码也是经过我写过几个版本锤炼过的。呵呵 在实际应用中,表现也是比较稳定的
当然,这是比较早期的了,以后再正正应用中,可能还需要做更多的处理,例如每个网络字节的缓冲,缓存等,以免过多字节造成socket出错等等
希望有兴趣的人继续留贴讨论,呵呵


点击下载此文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: