ActionScript简单实现Socket Tcp应用协议分析器

转自。。smark http://www.cnblogs.com/smark/archive/2012/05/15/2501507.html

ActionScript简单实现Socket Tcp应用协议分析器

    其实Flash上做通讯很多情况都选择AMF,毕竟他是AS内部基于对象进制序列协议,容量小效率高。但有时为了去调用一些已经有的Tcp服务,而这些服务并不是提供AMF支持;这时你就不得不实现一个协议的分析。其实AS提ByteArray提供了很多write和read方法,这样使我们应用起来非常方便。以下是用AS简单封装基于消息头描述大小的协议分析器。

    为了更好地管理消息,通过一接口来制写消息写入和读取规范。

package Beetle.AS
{
    import flash.utils.ByteArray;
    public interface IMessage
    {
        function Load(data:Reader):void;
        function Save(data:Writer):void;
    }
}
  接口比较简单分别是保让到流中和从流中获取,其中Reader和Writer都派生于ByteArray对象;为什么没有直接用ByteArray呢?其原因就可以自己实现更高级的信息获取方法.

package Beetle.AS
{
    import flash.net.getClassByAlias;
    import flash.utils.ByteArray;
    import flash.utils.getDefinitionByName;
    import mx.controls.Image;
    public class Reader extends ByteArray
    {
        public function Reader()
        {
            super();
        }
        public function ReadMessages(className:String):Vector.<IMessage>
        {
            var results:Vector.<IMessage> = new Vector.<IMessage>();
            for(var i:int=0;i<readInt();i++)
            {
                var msg:IMessage = IMessage(getDefinitionByName(className));
                results.push(msg);
            }
            return results;
        }
    }
}
package Beetle.AS
{
    import flash.utils.ByteArray;
    public class Writer extends ByteArray
    {
        public function Writer()
        {
            super();
        }
        public function WriteMessages(items:Vector.<IMessage>):void
        {
            writeInt(items.length);
            for each(var item:IMessage in items)
            {
                item.Save(this);
            }
        }
    }
}
  基础规则都构建好了,下面就开始做协议分析部分。

package Beetle.AS
{
    import flash.net.Socket;
    import flash.utils.ByteArray;
    import flash.utils.Endian;
    import mx.graphics.shaderClasses.ExclusionShader;
    public  class HeadSizeOfPackage
    {
        public function HeadSizeOfPackage()
        {
            mWriter.endian = Endian.LITTLE_ENDIAN;
            mReader.endian = Endian.LITTLE_ENDIAN;
        }
        private var mMessageReceive:Function;
        //消息接收回调函数
        public function get MessageReceive():Function
        {
            return mMessageReceive;
        }
        public function set MessageReceive(value:Function):void
        {
            mMessageReceive = value;
        }
        //写入消息类型标识
        protected  function WriteMessageTag(message:IMessage,data:Writer):void
        {
            throw new Error("WriteMessageTag not implement!");
        }
        //获取消息对象
        protected  function GetMessageByTag(data:Reader):IMessage
        {
            throw new Error("GetMessageByTag not implement!");
        }
        private var mReader:Reader = new Reader();
        private var mSize:int=0;
        //导入当前Socket接收的数据
        public function Import(socket:Socket):void
        {
            socket.endian = Endian.LITTLE_ENDIAN;
            while(socket.bytesAvailable>0)
            {
                if(mSize==0)
                {
                    mSize= socket.readInt()-4;
                    mReader.clear();
                }
                if(socket.bytesAvailable>= mSize)
                {
                   socket.readBytes(mReader,mReader.length,mSize);
                   var msg:IMessage = GetMessageByTag(mReader);
                   msg.Load(mReader);
                   if(MessageReceive!=null)
                       MessageReceive(msg);
                   mSize=0;
                }
                else{
                    mSize= mSize-socket.bytesAvailable;
                    socket.readBytes(mReader,mReader.length,socket.bytesAvailable);
                }
            }
        }
        private var mWriter:Writer = new Writer();
        //发磅封装的协议数据
        public function Send(message:IMessage,socket:Socket):void
        {
             socket.endian = Endian.LITTLE_ENDIAN;
             mWriter.clear();
             WriteMessageTag(message,mWriter);
             message.Save(mWriter);
             socket.writeInt(mWriter.length+4);
             socket.writeBytes(mWriter,0,mWriter.length);
             socket.flush();
        }
    }
}
  协议分析器的实现比较简单,基础功能有消息封装,对流进行分析还源对象并把消息回调到指定的函数中.MessageReceive是一个指向函数的属性,用于描述消息接收工作其原理类似于C#的委托。分析器中还有两个方法需要派生类重写WriteMessageTag和GetMessageByTag,其主要作用是写入消息类型标记和根据读取的标记信息创建相关联的对象。

     Send方法是一个协议包装过程,主要把对象写入流的信息加工后用指定的Socket对象发送出去。

public function Send(message:IMessage,socket:Socket):void
{
     socket.endian = Endian.LITTLE_ENDIAN;
     mWriter.clear();
     WriteMessageTag(message,mWriter);
     message.Save(mWriter);
     socket.writeInt(mWriter.length+4);
     socket.writeBytes(mWriter,0,mWriter.length);
     socket.flush();
}
  工作原理是通过消息接口的Save方法把对象信息写入到流中,第一步是先写入消息类型标记具体写入方法由派生类来确用string或int都可以,然后再写入消息内容;最后计算所有数据长度的头写入到socket再写入信息流即可。

    Import方法是一个数据导入工作,主要负责从Socket中读取数据进行加载分析。

public function Import(socket:Socket):void
{
    socket.endian = Endian.LITTLE_ENDIAN;
    while(socket.bytesAvailable>0)
    {
        if(mSize==0)
        {
            mSize= socket.readInt()-4;
            mReader.clear();
        }
        if(socket.bytesAvailable>= mSize)
        {
           socket.readBytes(mReader,mReader.length,mSize);
           var msg:IMessage = GetMessageByTag(mReader);
           msg.Load(mReader);
           if(MessageReceive!=null)
               MessageReceive(msg);
           mSize=0;
        }
        else{
            mSize= mSize-socket.bytesAvailable;
            socket.readBytes(mReader,mReader.length,socket.bytesAvailable);
        }
    }
}
  原理很简单如果当前需要加载的数据为零,则表示为一个表新的消息;读取该消息需要加载的数据的长度,然后从Socket读取数据写入到流中,值到读取的长度和当前消息长度一致的情况就加载消息,并通过回调函数把消息回调到具体的工作方法中.

     到这里一个以头4字节描述的消息分析器就完成,直接下来就是使用这个分析器。派生出一个新的分析器,并根据实际的需要实现对消息标记的处理.

public class HeadSizePackage extends HeadSizeOfPackage
{
    public function HeadSizePackage()
    {
        super();
    }
    override protected function GetMessageByTag(data:Reader):IMessage
    {
        var name:String = data.readUTF();
        switch(name)
        {
            case "Register":
                return new Register();
            case "User":
                return new User();
            case "GetUser":
                return new GetUser();
            default :
                return null;
        }
    }
    override protected function WriteMessageTag(message:IMessage, data:Writer):void
    {
         if(message is Register)
         {
             data.writeUTF("Register");
         }
         else if(message is User)
         {
             data.writeUTF("User");
         }
         else if(message is GetUser){
             data.writeUTF("GetUser");
         }
         else
         {
             data.writeUTF("NULL");
         }

    }
}
  对于消息对象的实现也很简单,只要实现IMessage接口即可

public class Register implements IMessage
{
    public function Register()
    {
    }
    public var UserName:String;
    public var EMail:String
    public function Load(data:Reader):void
    {
        UserName= data.readUTF();
        EMail = data.readUTF();
    }
    public function Save(data:Writer):void
    {
        data.writeUTF(UserName);
        data.writeUTF(EMail);
    }
}
  发送这个消息也比较简单

var reg:Register= new Register();
reg.UserName = txtUserName.text;
reg.EMail = txtEmail.text;
mPackage.Send(reg,mSocket);
  在使用AS的Socket时发现其实挺方便,很多基础的方法socket提供,即使是ByteArray也提供这些基础而又贴心的方法。
时间: 2024-08-29 03:16:59

ActionScript简单实现Socket Tcp应用协议分析器的相关文章

简单使用SOCKET,TCP,UDP模式之间的通信

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内[1] 另一个重要的传输协议.在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层.不同主机的应用层之间经常需要可靠的.像管道一样的连接,但是IP层不提供这样的流机制,而是提

python学习笔记-Day9 (TCP/IP协议、socket)

TCP/IP协议 TCP/IP四层协议 TCP/IP概念 tcp/ip协议是主机接入互联网以及接入互联网的两台主机通信的标准. 数据帧概念 数据帧 |-- 包头 | |--源地址 | |--目标地址 | |--数据类型 | |-- 数据 socket在四层协议中的位置 socket协议的交互流程 socket初试 # 依照上socket流程图,实现一个功能,客户端输入什么,就把输入的转为大写 # soceet server import socket ip_port=('127.0.0.1',9

深入浅出--iOS的TCP/IP协议族剖析&amp;&amp;Socket

深入浅出--iOS的TCP/IP协议族剖析&&Socket 简介 该篇文章主要回顾--TCP/IP协议族中的TCP/UDP.HTTP:还有Socket.(--该文很干,酝酿了许久!你能耐心看完吗?) 我在这个文章中,列举了常见的TCP/IP族中的协议,今天主角是--传输层协议. 传输层(Transport Layer)是OSI(七层模型)中最重要.最关键的一层,它负责总体的数据传输和数据控制的一层,传输层提供端到端(应用会在网卡注册一个端口号)的交换数据的机制,检查分组编号与次序.传输层对

JAVA基础知识之网络编程——-TCP/IP协议,socket通信,服务器客户端通信demo

OSI模型分层 OSI模型是指国际标准化组织(ISO)提出的开放系统互连参考模型(Open System Interconnection Reference Model,OSI/RM),它将网络分为七层:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层 TCP/IP协议 TCP/IP是一系列网络通信协议的统称,其中最核心的两个协议是TCP和IP.TCP称为传输控制协议,IP称为互联网络协议. 网络分层除了OSI模型分层,还有TCP/IP模型分层,将网络划分为四层,应用层.传输层.网际层

Linux程序设计学习笔记----Socket网络编程基础之TCP/IP协议簇

转载请注明出处: ,谢谢! 内容提要 本节主要学习网络通信基础,主要涉及的内容是: TCP/IP协议簇基础:两个模型 IPv4协议基础:IP地址分类与表示,子网掩码等 IP地址转换:点分十进制\二进制 TCP/IP协议簇基础 OSI模型 我们知道计算机网络之中,有各种各样的设备,那么如何实现这些设备的通信呢? 显然是通过标准的通讯协议,但是,整个网络连接的过程相当复杂,包括硬件.软件数据封包与应用程序的互相链接等等,如果想要写一支将联网全部功能都串连在一块的程序,那么当某个小环节出现问题时,整只

iOS的TCP/IP协议族剖析&amp;&amp;Socket

原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 简介 该篇文章主要回顾--TCP/IP协议族中的TCP/UDP.HTTP:还有Socket.(--该文很干,酝酿了许久!你能耐心看完吗?O_o) 我在这个文章中,列举了常见的TCP/IP族中的协议,今天主角是--传输层协议. 传输层(Transport Layer)是OSI(七层模型)中最重要.最关键的一层,它负责总体的数据传输和数据控制的一层,传输层提供端到端(应用会在网卡注

iOS 的 TCP/IP 协议族剖析 &amp;&amp; Socket

简介 该篇文章主要回顾–TCP/IP协议族中的TCP/UDP.HTTP:还有Socket.(--该文很干,酝酿了许久!你能耐心看完吗?O_o) 我在这个文章中,列举了常见的TCP/IP族中的协议,今天主角是--传输层协议. 传输层(Transport Layer)是OSI(七层模型)中最重要.最关键的一层,它负责总体的数据传输和数据控制的一层,传输层提供端到端(应用会在网卡注册一个端口号)的交换数据的机制,检查分组编号与次序.传输层对其上三层如会话层等,提供可靠的传输服务,对网络层提供可靠的目的

[转] 3个学习Socket编程的简单例子:TCP Server/Client, Select

以前都是采用ACE的编写网络应用,最近由于工作需要,需要直接只用socket接口编写CS的代码,重新学习这方面的知识,给出自己所用到的3个简单例子,都是拷贝别人的程序.如果你能完全理解这3个例子,估计socket编程就已经基本入门了. 建议:1) 多多查查所用到的网络接口; 2) 最好有一本书,如UNIX环境高级编程,UNIX网络编程,可查询:3) 可以直接使用书上的例子更好. http://blog.csdn.net/zhenjing/article/details/4770490 TCP C

TCP/IP协议学习(四) 基于C# Socket的Web服务器---静态资源处理

目录 1. C# Socket通讯 2. HTTP 解析引擎 3. 资源读取和返回 4. 服务器测试和代码下载 Web服务器是Web资源的宿主,它需要处理用户端浏览器的请求,并指定对应的Web资源返回给用户,这些资源不仅包括HTML文件,JS脚本,JPG图片等,还包括由软件生成的动态内容.为了满足上述需求,一个完整的Web服务器工作流程: 1) 服务器获得浏览器通过TCP/IP连接向服务器发送的http请求数据包. 2) HTTP请求经过Web服务器的HTTP解析引擎分析得出请求方法.资源地址等