1. 转自。。smark http://www.cnblogs.com/smark/archive/2012/05/15/2501507.html
  2.  
  3. ActionScript简单实现Socket Tcp应用协议分析器
  4.  
  5. 其实Flash上做通讯很多情况都选择AMF,毕竟他是AS内部基于对象进制序列协议,容量小效率高。但有时为了去调用一些已经有的Tcp服务,而这些服务并不是提供AMF支持;这时你就不得不实现一个协议的分析。其实ASByteArray提供了很多writeread方法,这样使我们应用起来非常方便。以下是用AS简单封装基于消息头描述大小的协议分析器。
  6.  
  7. 为了更好地管理消息,通过一接口来制写消息写入和读取规范。
  8.  
  9. package Beetle.AS
  10. {
  11. import flash.utils.ByteArray;
  12. public interface IMessage
  13. {
  14. function Load(data:Reader):void;
  15. function Save(data:Writer):void;
  16. }
  17. }
  18.   接口比较简单分别是保让到流中和从流中获取,其中ReaderWriter都派生于ByteArray对象;为什么没有直接用ByteArray呢?其原因就可以自己实现更高级的信息获取方法.
  19.  
  20. package Beetle.AS
  21. {
  22. import flash.net.getClassByAlias;
  23. import flash.utils.ByteArray;
  24. import flash.utils.getDefinitionByName;
  25. import mx.controls.Image;
  26. public class Reader extends ByteArray
  27. {
  28. public function Reader()
  29. {
  30. super();
  31. }
  32. public function ReadMessages(className:String):Vector.<IMessage>
  33. {
  34. var results:Vector.<IMessage> = new Vector.<IMessage>();
  35. for(var i:int=0;i<readInt();i++)
  36. {
  37. var msg:IMessage = IMessage(getDefinitionByName(className));
  38. results.push(msg);
  39. }
  40. return results;
  41. }
  42. }
  43. }
  44. package Beetle.AS
  45. {
  46. import flash.utils.ByteArray;
  47. public class Writer extends ByteArray
  48. {
  49. public function Writer()
  50. {
  51. super();
  52. }
  53. public function WriteMessages(items:Vector.<IMessage>):void
  54. {
  55. writeInt(items.length);
  56. for each(var item:IMessage in items)
  57. {
  58. item.Save(this);
  59. }
  60. }
  61. }
  62. }
  63.   基础规则都构建好了,下面就开始做协议分析部分。
  64.  
  65. package Beetle.AS
  66. {
  67. import flash.net.Socket;
  68. import flash.utils.ByteArray;
  69. import flash.utils.Endian;
  70. import mx.graphics.shaderClasses.ExclusionShader;
  71. public class HeadSizeOfPackage
  72. {
  73. public function HeadSizeOfPackage()
  74. {
  75. mWriter.endian = Endian.LITTLE_ENDIAN;
  76. mReader.endian = Endian.LITTLE_ENDIAN;
  77. }
  78. private var mMessageReceive:Function;
  79. //消息接收回调函数
  80. public function get MessageReceive():Function
  81. {
  82. return mMessageReceive;
  83. }
  84. public function set MessageReceive(value:Function):void
  85. {
  86. mMessageReceive = value;
  87. }
  88. //写入消息类型标识
  89. protected function WriteMessageTag(message:IMessage,data:Writer):void
  90. {
  91. throw new Error("WriteMessageTag not implement!");
  92. }
  93. //获取消息对象
  94. protected function GetMessageByTag(data:Reader):IMessage
  95. {
  96. throw new Error("GetMessageByTag not implement!");
  97. }
  98. private var mReader:Reader = new Reader();
  99. private var mSize:int=0;
  100. //导入当前Socket接收的数据
  101. public function Import(socket:Socket):void
  102. {
  103. socket.endian = Endian.LITTLE_ENDIAN;
  104. while(socket.bytesAvailable>0)
  105. {
  106. if(mSize==0)
  107. {
  108. mSize= socket.readInt()-4;
  109. mReader.clear();
  110. }
  111. if(socket.bytesAvailable>= mSize)
  112. {
  113. socket.readBytes(mReader,mReader.length,mSize);
  114. var msg:IMessage = GetMessageByTag(mReader);
  115. msg.Load(mReader);
  116. if(MessageReceive!=null)
  117. MessageReceive(msg);
  118. mSize=0;
  119. }
  120. else{
  121. mSize= mSize-socket.bytesAvailable;
  122. socket.readBytes(mReader,mReader.length,socket.bytesAvailable);
  123. }
  124. }
  125. }
  126. private var mWriter:Writer = new Writer();
  127. //发磅封装的协议数据
  128. public function Send(message:IMessage,socket:Socket):void
  129. {
  130. socket.endian = Endian.LITTLE_ENDIAN;
  131. mWriter.clear();
  132. WriteMessageTag(message,mWriter);
  133. message.Save(mWriter);
  134. socket.writeInt(mWriter.length+4);
  135. socket.writeBytes(mWriter,0,mWriter.length);
  136. socket.flush();
  137. }
  138. }
  139. }
  140.   协议分析器的实现比较简单,基础功能有消息封装,对流进行分析还源对象并把消息回调到指定的函数中.MessageReceive是一个指向函数的属性,用于描述消息接收工作其原理类似于C#的委托。分析器中还有两个方法需要派生类重写WriteMessageTag和GetMessageByTag,其主要作用是写入消息类型标记和根据读取的标记信息创建相关联的对象。
  141.  
  142. Send方法是一个协议包装过程,主要把对象写入流的信息加工后用指定的Socket对象发送出去。
  143.  
  144. public function Send(message:IMessage,socket:Socket):void
  145. {
  146. socket.endian = Endian.LITTLE_ENDIAN;
  147. mWriter.clear();
  148. WriteMessageTag(message,mWriter);
  149. message.Save(mWriter);
  150. socket.writeInt(mWriter.length+4);
  151. socket.writeBytes(mWriter,0,mWriter.length);
  152. socket.flush();
  153. }
  154.   工作原理是通过消息接口的Save方法把对象信息写入到流中,第一步是先写入消息类型标记具体写入方法由派生类来确用stringint都可以,然后再写入消息内容;最后计算所有数据长度的头写入到socket再写入信息流即可。
  155.  
  156. Import方法是一个数据导入工作,主要负责从Socket中读取数据进行加载分析。
  157.  
  158. public function Import(socket:Socket):void
  159. {
  160. socket.endian = Endian.LITTLE_ENDIAN;
  161. while(socket.bytesAvailable>0)
  162. {
  163. if(mSize==0)
  164. {
  165. mSize= socket.readInt()-4;
  166. mReader.clear();
  167. }
  168. if(socket.bytesAvailable>= mSize)
  169. {
  170. socket.readBytes(mReader,mReader.length,mSize);
  171. var msg:IMessage = GetMessageByTag(mReader);
  172. msg.Load(mReader);
  173. if(MessageReceive!=null)
  174. MessageReceive(msg);
  175. mSize=0;
  176. }
  177. else{
  178. mSize= mSize-socket.bytesAvailable;
  179. socket.readBytes(mReader,mReader.length,socket.bytesAvailable);
  180. }
  181. }
  182. }
  183.   原理很简单如果当前需要加载的数据为零,则表示为一个表新的消息;读取该消息需要加载的数据的长度,然后从Socket读取数据写入到流中,值到读取的长度和当前消息长度一致的情况就加载消息,并通过回调函数把消息回调到具体的工作方法中.
  184.  
  185. 到这里一个以头4字节描述的消息分析器就完成,直接下来就是使用这个分析器。派生出一个新的分析器,并根据实际的需要实现对消息标记的处理.
  186.  
  187. public class HeadSizePackage extends HeadSizeOfPackage
  188. {
  189. public function HeadSizePackage()
  190. {
  191. super();
  192. }
  193. override protected function GetMessageByTag(data:Reader):IMessage
  194. {
  195. var name:String = data.readUTF();
  196. switch(name)
  197. {
  198. case "Register":
  199. return new Register();
  200. case "User":
  201. return new User();
  202. case "GetUser":
  203. return new GetUser();
  204. default :
  205. return null;
  206. }
  207. }
  208. override protected function WriteMessageTag(message:IMessage, data:Writer):void
  209. {
  210. if(message is Register)
  211. {
  212. data.writeUTF("Register");
  213. }
  214. else if(message is User)
  215. {
  216. data.writeUTF("User");
  217. }
  218. else if(message is GetUser){
  219. data.writeUTF("GetUser");
  220. }
  221. else
  222. {
  223. data.writeUTF("NULL");
  224. }
  225.  
  226. }
  227. }
  228.   对于消息对象的实现也很简单,只要实现IMessage接口即可
  229.  
  230. public class Register implements IMessage
  231. {
  232. public function Register()
  233. {
  234. }
  235. public var UserName:String;
  236. public var EMail:String
  237. public function Load(data:Reader):void
  238. {
  239. UserName= data.readUTF();
  240. EMail = data.readUTF();
  241. }
  242. public function Save(data:Writer):void
  243. {
  244. data.writeUTF(UserName);
  245. data.writeUTF(EMail);
  246. }
  247. }
  248.   发送这个消息也比较简单
  249.  
  250. var reg:Register= new Register();
  251. reg.UserName = txtUserName.text;
  252. reg.EMail = txtEmail.text;
  253. mPackage.Send(reg,mSocket);
  254.   在使用ASSocket时发现其实挺方便,很多基础的方法socket提供,即使是ByteArray也提供这些基础而又贴心的方法。

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

  1. Http,Socket,TCP/IP 协议简述

    Http,Socket,TCP/IP 协议简述:https://blog.csdn.net/gordohu/article/details/54097841 TCP/IP协议,HTTP协议与webSo ...

  2. 简单聊聊HTTP/TCP/IP协议

    经过几天的面试,有很多公司的面试官都会问到是否了解HTTP/TCP/IP协议? 一遇到这个问题,就一脸懵逼,虽然是计算机基层的东西,看来是必须得了解的,回到家之后,就查找了一些资料,整理了一篇博客,简 ...

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

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机网络OSI模型中, ...

  4. 使用Beetle简单构建高性能Socket tcp应用

    beetle是基于c#编写的高性能Socket tcp组件,它基于SocketAsyncEventArgs的实现并提供了发送队列和接收队列的支持,可以根据情况灵活地设置1-N个发送队列和接收队列.除了 ...

  5. socket、tcp/ip协议、udp协议

    socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Un ...

  6. TCP/IP 协议介绍

    转自http://blog.jobbole.com/104886/ 一.TCP/IP 协议介绍 在介绍 HTTP 协议之前,先简单说一下TCP/IP协议的相关内容.TCP/IP协议是分层的,从底层至应 ...

  7. 门面模式的典型应用 Socket 和 Http(post,get)、TCP/IP 协议的关系总结

    门面模式的一个典型应用:Socket 套接字(Socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息: 连接使用的 ...

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

    目录 1. C# Socket通讯 2. HTTP 解析引擎 3. 资源读取和返回 4. 服务器测试和代码下载 Web服务器是Web资源的宿主,它需要处理用户端浏览器的请求,并指定对应的Web资源返回 ...

  9. TCP/IP协议学习(五) 基于C# Socket的C/S模型

    TCP/IP协议作为现代网络通讯的基石,内容包罗万象,直接去理解理论是比较困难的:然而通过实践先理解网络通讯的理解,在反过来理解学习TCP/IP协议栈就相对简单很多.C#通过提供的Socket API ...

随机推荐

  1. 【LeetCode练习题】Minimum Depth of Binary Tree

    Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum depth is the n ...

  2. iOS 之点击按钮改变状态的图片

    .h  文件中 @property (strong, nonatomic) IBOutletUIButton *publishBtton; @property (strong, nonatomic) ...

  3. javadoc 生成帮助文档时,注意以下几点

    参考:http://www.w3school.com.cn/tags/tag_pre.asp javadoc 生成帮助文档时,注意以下几点: 1.函数功能描述的结尾一定要有句号,英文句号或中文句号均可 ...

  4. sql语句收集

    一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备 ...

  5. java一个简单的管理系统

    用java实现的简单管理系统 运行出来的状态 实现了新增.删除.借出.归还.排行榜简单的功能! 下面是简单的代码 首先定义一个书籍类,自己打开哦! public class Book implemen ...

  6. Old Sorting(转化成单调序列的最小次数,置换群思想)

     Old Sorting Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit S ...

  7. telnet查看memcached运行参数说明

    在Linux/Windows系统中启动memcached的命令请查看http://weilingfeng98.iteye.com/admin/blogs/1741179 启动完memcached服务器 ...

  8. webpack构建具备版本管理能力的项目

    webpack是时下十分流行的编译和打包工具,它提供一种可扩展的loader的方式,简单的配置,便可以编译打包各类型的文件,包括js.css.image.font.html,以及各种预编译语言都不在话 ...

  9. thinkphp的条件的多种写法

    class SelectAction extends Action{   function index(){ //thinkphp 查询语言  //         1.普通查询 //   2.区间查 ...

  10. <httpRuntime>

    1.在webconfig中httpconfig属性只能出现一次 配置httpRunTime也可以让FileUpload上传更大的文件,不过设置太大了会因用户将大量文件传递到该服务器而导致的拒绝服务攻击 ...