1.socket 解码
下述内容为转载,对socket解码代码设计有帮助:
主要想说一下socket解码在设计时忽略的一个问题。(感谢Lite3的反馈)。
对于客户端的Socket的数据基本读取方式一般来说可以分为三种:
1、按照数据流的结尾标记截取
2、按照包头记录的包长度截取
3、按照包长度截取并验证结尾标记。
第一种方式:如图,通常做发是每个包结尾发送一个\0标记,表示这个数据包发送完了。socket每次读取1个字节直到遇到结尾符,结束读取将数据包传递到逻辑层。这种方式在xmlSocket时就已经用了很多了。
第二种方式:如图包头用一个整型记录完整包的长度。每次都先读取一个包长度,然后按照包长度读取指定长度的数据作为一个完整数据包传递到到逻辑层。
第三种方式:如图。这种方式把以上两种方式做了结合,读取的时候无需一个一个字节读,直接读取指定长度。结尾符可以用来做校验判定,同时可以作为包长度字节的读取依据。(如果上一个包有问题可以丢弃之后,以结尾符为标记读取下一个包的包长度。)
介绍了一点基本原理,下面说一下这个设计缺陷。
问题:
通讯中我们使用的是第二种方式——包长读取。在通讯类中创建一个临时存储变量_dataArray,提供一个getData():*公用方法,供外部取出数据。每次读完一个完整包后压入_dataArray,同时触发"recievedData"事件。代码如下:
private function socketDataHandler(event:ProgressEvent):void
{
//_readFlag:int;//0表示全部读完了,1表示长度读取完毕 2表示正在读取数据
while (bytesAvailable)
{
if (_readFlag == 0&&bytesAvailable>=4)
{
_length = Number(readInt());
_readFlag=1
}
if (_readFlag == 1 && bytesAvailable >= _length)
{
var temp:Object = readObject();
_dataArray.push(temp);
dispatchEvent(new Event("recievedData"));//
_length = 0;
_readFlag = 0;
}
}
}
以上代码从结构上看是没有任何问题的,而且在测试前期我们也一直用着没有任何问题。逻辑相当清楚:接收到socket的事件后首先读取一个包长,然后按照包长读取数据。读取完毕发出事件。。。
那么,问题终于来了——网友Lite3出现了。^ _ ^
Lite3发来了一个出错提示:
Error: Error #1502: 脚本的执行时间已经超过了 15 秒的默认超时设置。
at qdooo.net::mySocket/socketDataHandler()
相信大家一看就能知道问题出在了哪里——问题就在while上。
while的循环等待时间因为某种原因超过了15秒。这里所指的某种原因就是网速,那天Lite3那边的网速非常慢。这样一来放大了设计中一处缺陷所照成的影响——必须等到可读数据的长度等于或者大于包长度的时候才开始读取,也就是下面这句:
if (_readFlag == 1 && bytesAvailable >= _length)
正是由于这个判断做了限定,如果数据长度不够,那么他会在while中一直循环等待。直到超过15秒报错。
解决:
分析好了原因那么就很好解决了,想办法读空流里面的数据让while跳出等待就行了。
读后:测试时,使用php 作socketserver ,连续发送定长string 到 as3 中,几点注意:
- 接收时,buffer长度为一次接收所有的string长度和;
- 而as3的read读取后,socket.bytesAvailable长度减去所读的长度,直至读取完毕;
- 按照前面转载的代码方式,就可以顺利接收;
2.粘包问题
注意,每一次的读取ba.readBytes(temp,offest,length);方法,真实的position=offest都是从当前的位置为起点+上一次的位置,length就是长度了
var ba:ByteArray=new ByteArray();
ba.writeUTFBytes("for test for tews for test for tewsfor test for tews");
// ba.writeUnsignedInt(15);
trace(ba.length);
ba.position=0;
for(var i:uint=0;ba.bytesAvailable;i++)
{
var temp:ByteArray=new ByteArray();
ba.readBytes(temp,2,4);
trace("\n",temp.readUnsignedInt(),"ba.postion",ba.position);
}
}
52
26223 ba.postion 4
29797 ba.postion 8
8294 ba.postion 12
8308 ba.postion 16
29472 ba.postion 20
29216 ba.postion 24
29556 ba.postion 28
28530 ba.postion 32
25975 ba.postion 36
28530 ba.postion 40
25971 ba.postion 44
26223 ba.postion 48
29797 ba.postion 52
3.汉字乱码问题
正所谓眼见为实,耳听为虚,在编程开发时,听别人说的东西一定要自己进行验证。因为网络这个东西,跟风的东西太多,以讹传讹的事情比比皆是。
近来在做AS3与.net的socket通信工作,相继解决了通信协议解析和数据粘包等问题,终于要跟汉字编码这个问题一争高下了。在经历了一番深入研究之后,我终于将汉字乱码这个问题彻底解决了,以后不管它AS3的socket要跟谁通信,我的办法都可以让你在面临汉字乱码问题时知道该怎么办了。
要说as3的socket发送汉字,首先得认识as3的两个类:flash.net.Socket和flash.utils.ByteArray,这两个类的协作关系就是ByteArray
将字符串(包括汉字)按照特定的编码格式转化成字节数组,然后Socket类将这个字节数组发送出去。整体思路是很简单的。
但是这里面有个陷阱或者说很多人在讲解flash乱码问题时没有说清楚的问题。这也是我开始遇到乱码问题时非常困惑的地方。首先,我们来介绍这个问题的所在:
ByteArray有两个函数可以转化汉字成字节数组:
第一个是writeMultiByte;另
第二个是writeUTFBytes;
这两个方法有何区别?
这正是乱码问题之所在!我们来做个试验加以说明.试验方式如下:设定一个字符串“曹操”,然后分别用ByteArray的这两个方法将其转化成字节数组,然后读出字节数组的内容看看结果,看到字节数组内容的时候大家就会有所收获了。
var arrBuffer:ByteArray=new ByteArray(); var strTest:String="曹操"; arrBuffer.writeMultiByte(strTest,"utf8");
读出这个字节数组的内容,得到的字节值是:-78 -36 -78 -39 ,每个汉字占两个字节。我们在来看下面的例子var arrBuffer:ByteArray=new ByteArray(); var strTest:String="曹操"; //arrBuffer.writeMultiByte(strTest,"utf8"); arrBuffer.writeUTFBytes(strTest); 读出这个字节数组的内容,得到的字节值是:-26 -101 -71 -26 -109 -115 ,很明显的,每个汉字占到三个字节。
陷阱已经显露出来了,在解决汉字乱码这个问题的时候,我查了很多的网上信息,见到最多的一行代码就是arrBuffer.writeMultiByte(strTest,"utf8")了,也不做什么说明,根本就是误人子弟嘛。现在,这个问题被我揪出来了。大家如果还有什么疑问,就继续往下看。
经我查证,Unicode字符集在编码汉字的时候,应该是一个汉字三个字节的,为何第一次试验的时候用arrBuffer.writeMultiByte(strTest,"utf8");得到的却是一个汉字两个字节呢?我又试验性的将编码格式那个参数换成"gbk"和"gb2312",结果得到的字节数组与"utf8"时一样。我还没有搞清楚这是参数失效还是Adobe有别的什么考虑。但是试验已经很清楚的告诉我们了一个事实:如果你想将汉字用真正的UTF-8编码的话,就用ByteArray的writeUTFBytes函数来解决问题。不要再用writeMultiByte(strTest,"utf8")了。这个函数是不会将汉字转化成UTF编码的。
至于.net端,我就不多着笔墨了,要在.net端转化汉字编码时,Encoding和UnicodeEncoding这两个类打开看看,使用合适的编码类和函数就可以解决问题了。实在还是有问题,按照我解决flash端编码的经验,查看实际编码得到的字节值,你也就能够找到合适的编码集来解决问题了。
分享到:
相关推荐
在AS3中,我们可以使用Socket类来实现这一功能。本示例主要探讨如何在Flash AS3中使用Socket类来发送和接收16进制数据。 首先,让我们理解16进制。16进制(Hexadecimal)是一种逢16进1的进位制,主要用于表示计算机...
本文将深入探讨基于ActionScript 3(AS3)的Socket通信,包括客户端与服务端的交互,以及如何通过提供的实例来理解这一过程。我们将不涉及具体代码,而是详细解释相关的概念和技术要点。 首先,Socket是网络编程中...
AS3中的`Socket`类是Flash Player 9引入的新特性,用于创建基于TCP/IP协议的网络连接。Socket连接允许应用程序直接与远程服务器进行低级别的数据通信,而不依赖于特定的应用层协议,如HTTP或HTTPS。这种直接的连接...
下面是关于 Flash AS3.0 Socket 编程的重要知识点: 1. 与 Socket 服务器建立连接 在使用 Socket 编程时,首先需要与 Socket 服务器建立连接。我们可以通过调用 Socket.connect() 或 XMLSocket.connect() 方法来...
### AS3 Socket编程详解 #### 一、引言 在当今互联网时代,实时通信变得尤为重要。ActionScript 3.0(AS3)作为Flash平台的主要编程语言之一,提供了强大的网络功能,包括Socket编程的支持。本文将详细介绍AS3中的...
本文将深入探讨AS3中的Socket通信方式,特别是利用XMLSocket进行网络交互的细节。 首先,XMLSocket是AS3中用于低级网络通信的类,它提供了双向、全双工的数据流,适合于游戏开发中的实时数据交换,如玩家状态同步、...
### AS3使用Socket的简单例子 #### 知识点概览 - **AS3 Socket编程基础** - **创建与配置XMLSocket对象** - **事件监听器的设置与使用** - **连接服务器及发送数据** - **接收服务器响应** #### 知识点详细解析 #...
资源名称:flash as3.0 socket编程 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
本篇文章将探讨如何解决AS3中的安全沙箱问题,以便与Java后台进行顺畅的Socket通信。 首先,我们需要了解AS3的安全沙箱模型。AS3的沙箱分为三类:本地信任的沙箱(Local-with-Files)、网络沙箱(Network)和本地...
AS3(ActionScript 3)和Java都是常用于创建跨平台应用的语言,而Socket编程则提供了底层的网络通信接口。本篇将深入探讨如何使用AS3与Java通过简单的Socket进行交互。 **AS3中的Socket通信** AS3是Adobe开发的脚本...
### Flash AS3 Socket编程基础知识详解 #### 一、引言 在现代互联网应用开发中,实时通信技术变得越来越重要。而Socket编程作为一种实现客户端与服务器之间实时数据交换的有效手段,在Flash开发领域同样占据着重要...
本文将深入探讨“as3-java socket”这个主题,这是关于使用ActionScript 3(AS3)与Java进行Socket通信的一个测试程序。AS3是Adobe Flash Platform的主要编程语言,而Java Socket API则是用于实现网络上的双向通信的...
as3socket写的rtmp协议类,完成基本的连接功能,可以获取服务器返回的16进制数据
以下是一些关于AS3.0 Socket通信的关键知识点: 1. **创建Socket对象**: 首先,我们需要创建一个`Socket`对象实例,通过调用其构造函数指定服务器的IP地址和端口号。例如: ```as3 var socket:Socket = new ...
AS3中的SOCKET技术是ActionScript 3.0中用于实现网络通信的一种方式,它允许客户端(通常是Flash应用程序)与服务器之间进行低级的、基于TCP/IP协议的双向数据传输。在AS3中,有两种主要的类用于实现SOCKET通信:...
标题中的“flash as3/java socket 聊天室”指的是使用Adobe Flash ActionScript 3(AS3)语言和Java的Socket编程技术实现的一个在线聊天应用程序。这个应用允许用户通过网络进行实时通信,创建一个基本的聊天环境。...
### 关于AS3 Air ServerSocket支持WebSocket的知识点 在Adobe Flash Platform中,ActionScript 3 (AS3) 提供了创建高性能网络应用的能力。本文将详细介绍如何利用 AS3 和 Adobe AIR 的 `ServerSocket` 类来实现一个...
AS3 Socket基础知识是网络通信的重要组成部分,特别是在网络时代,它被广泛应用于各种应用程序中,因为“一切皆Socket”。网络进程间的通信需要一个唯一标识,TCP/IP协议族通过IP地址识别网络主机,结合传输层的...