- 浏览: 416266 次
- 性别:
- 来自: 济南
最新评论
-
nianshi:
slideDown就是show的滑动效果版本, slideUp ...
Jquery零碎代码收藏 -
nianshi:
以后编写JS代码,少写<div onclick=&quo ...
Jquery零碎代码收藏 -
nianshi:
获取匹配元素相对父元素的偏移var p = $("p ...
Jquery零碎代码收藏 -
nianshi:
获取匹配元素在当前窗口的相对偏移var p = $(" ...
Jquery零碎代码收藏 -
wuchu:
谢谢
Flex 读取XML配置文件总结
在使用ActionScript3.0进行编程的时候需要注意以下问题:
1、与Socket服务器建立连接。
2、向Socket服务器发送数据。
3、从Socket服务器读数据。
4、同Socket服务器进行握手,并确定收到了什么样的数据和如何处理这些数据。
5、与Socket服务器断开,或者当服务器想与你断开的时候发消息给你。
6、处理使用Socket时候引发的错误。
实例详解:
一、通过Socket.connect()或者XMLSocket.connect()方法并监听网络连接的事件消息。
连接一台Socket服务器你需要确定两个信息,一个是Socket服务器的域名或者IP地址,另一个是服务器监听的端口号。
无论你使用的是Socket还是XMLSocket类的实例,连接请求都是完全的一样的,两个类都是使用一个名叫connect()的方法,该方法有两个参数:host和port。
host:该参数为字符串类型,可以是一个域名,也可以是一个IP地址。如果Socket服务器与你该Flash影片发布的Web服务器是同一个,该参数为Null。
Port:该参数为一个表示Socket服务器监听端口的Int值,该值最小为1024,除非在服务器中有一个Policy文件用于指定允许端口号小于1024。
因为Flash Socket编程是一个异步的过程,connect() 方法不会等到一个连接完成后再执行下一行代码的执行。如果你想在一个连接完全执行完之前与一个Socket完全绑定,那么你将会得到一个意想不到的结果,并且你当前的代码将不能工作。
在尝试一个新的Socket连接的时候我们最好先添加一个连接事件监听器。当一个连接建立成功,Socket或者XMLSocket会发出一个连接事件,这就可以让你知道交互已经准备好了。
下面举一个Socket实例与本地Socket服务器的6666端口建立连接的例子:
package{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
public class SocketExample extends Spirte{
private var socket:Socket;
public function SocketExample(){
socket=new Socket();
socket.addEventListener(Event.CONNECT,onConnect);//注册侦听函数
socket.connect("localhost",6666);//连接本地服务器6666端口
}
private function onConnect(e:Event):void{
trace("正在连接服务器...");
}
}
}
如果你想通过XMLSocket与服务器建立连接只需要把上面的Socket换成XMLSocket。
如果连接失败,可能是下面两种原因:一种是连接立即失败和运行时错误,另一种是如果无法完成连接从而产生一个ioError或者securityError事件。
请牢记,当与一个主机建立一个Socket连接时,Flash Player要遵守如下安全沙箱规则:
1、Flash的.swf文件和主机必须严格的在同一个域名,只有这样才可以成功建立连接。
2、一个从网上发布的.swf文件是不可以访问本地服务器的。
3、本地未通过认证的.swf文件是不可以访问任何网络资源的。
4、你想跨域访问或者连接低于1024的端口,必须使用一个跨域策略文件。
如果尝试连接未认证的域或者低端口服务,这样就违反了安全沙箱策略,同时会产生一个securityError事件。这些情况都可以通过一个跨域 策略文件解决,无论是Socket对象还是XMLSocket对象的策略文件,都必须在连接之前通过使用 flash.system.Security.loadPolicyFile()方法载入策略文件,具体如 下:Security.loadPolictyFile("http://www.example.cn/crossdomain.xml");
二、向Socket服务器发送数据。
对于Socket对象来说,通过用write方法(writeByte(),writeUTFBytes()等方法),先向缓存区写入数据,然后使用flush()方法发送数据,对于XMLSocket对象,使用send()方法。
当你使用Socket对象向服务器发送数据的时候,你首先要将数据写入到一个缓冲区中。Socket类设置了一系列的方法来写数据。每一个方法都 用于写不同的数据类型的数据,这些方法分别 是:writeBoolean(),writeByte(),writeBytes(),writeDouble(),writeFloat(),writeInt(),writeMultiByte(),writeObject(),writeShort(),writeUnsignedInt(),writeUTF() 和writeUTFBytes()。这些方法大多数都只接受一个参数,该参数的类型同方法的名字相匹配。例如:writeBoolean()方法接受一个 布尔值作为参数,而 writeByte(),writeDouble(),writeFloat(),writeInt(),writeShort(),writeUnsignedInt() 方法接受一个数字型参数。writeObject()方法接受一个对象类型作为参数。但该对象必须序列化成为AMF格式。writeBytes()方法允 许你传一个ByteArray参数,并带有偏移量和长度两个参数。例如,下面这段代码,调用了一个writeBytes()方法,该方法将 ByteArray对象中的所有byte值都传出 去:socket.writeBytes(byteArray,0,byteArray.length);
writeUTF()和writeUTFBytes()方法允许你的发送字符串类型的参数。每一个方法只接受一个字符串作为参数。 writeUTFBytes()方法简单的将字符串作为Bytes发送。writeUTF()方法在写入真正数据之前,先写入bytes的数量。
writeMultiByte()方法也允许字符串类型的参数,但是使用的为非默认字符集。该方法需要两个参数:字符串和字符集名称。在 Flash和Flex的帮助文档中有一个自持所有字符集的列表,该列表中的标签和描述符是--对应的,使用标签值作为writeMultiByte()作 为字符集。例如下面的代码发送一个编码为Unicode的字符 串:socket.writeMultiByte("example","unicode");
向一个Socket对象传数值的方法完全依赖于你所有数据的类型和服务所接受数据的类型,使用一个Socket对象,你完全可以使用 ActionScript写一个Telnet和POP mail客户端,这两种协议都支持ASCII字符指令。例如:在连接一个POP服务器之后,你可通过使用USER指令指定一个用户,下面代码向一个 Socket对象发一条指令:socket.writeUTFBytes("USER exampleUsername\n");
向一个Socket对象写入数据其实并没有将数据发送到Socket服务器。每调用一个write方法都向Socket对象添加一个数据。当你想 将这些累积的数据发送到Socket服务器需要调用flush()方法,flush()方法调用之后将把所有已经写入的数据发送出去,并清空缓冲 区:socket.flush();
XMLSocket类是一个非常简单用于发送数据的API,写于发数据都是由send()这一方法来完成。send()方法可以接受任何数据类型 的参数,它可以将所有的参数都转换为一个字符串类型并发送到服务器,通常参数为一个XML对象或者一个包含数据结构类似XML数据的字符 串:xmlSocket.send();
然后,准备的格式完全依赖于服务器所能够接受的格式。如果服务器接受XML格式的数据,你必须发送XML格式的数据。如果服务器只接受URL编码的数据,你也必须发送URL编码的数据。
三、从Socket服务器读数据
对于Socket实例,先收到socketData事件,然后调用如下两个方法的一个,比如:readByte()或者readInt(),在事件控制器吕确定不会去读过去的bytesAvailable.
对于XMLSocket实例,先收到data事件,然后解析从事件控制器内部装载的XML数据。
socket在Flash中是一个异步的行为,因此,它就不能简单的创建一个Socket连接,然后就立该尝试去读取数据。read方法不能等到 从服务器传过来数据之后在返回。换句话说,你只能在客户端从服务器载入所有数据之后才可以读取数据。在数据可用之前读数据会产生一个错误。
通过socketData事件广播到Socket实例,这样我们就可以知道什么时候数据可以被读取。那么我们要为socketData事件添加一 个事件监听器,任何时候只要有新的数据从一个socket服务器发送过来,都会触发事件控制器。在事件处理器的内部我们写入我们要执行的代码去读取和处理 收到的数据。
从一个前端服务器读取数据,Socket类为我们提供了许多不同的方法,这些方法依赖于你所读得数据类型。例如,你可以通过readByte() 方法读一个byte()数据,或者通过一个使用readUnsignedInt()方法去读一个无符号整数。下面这个表列出来能够从服务器读取的数据类 型,返回值和read方法每次读入的字节数。
方法:返回值类型 字节数 描述
readBoolean():Boolean 1 从Socket读取一个Boolean值
readByte():int 1 从Socket读取一个Byte值
readDouble():Number 8 从Socket读取一个IEEE 754双精度浮点数
readFloat():Number 4 从Socket读取一个IEEE 754单精度浮点数
readInt():int 4 从Socket读取一个有符号32-bit整数值
readObject():* n 从Socket读取一个AMF-encoded对象
readShort():int 2 从Socket读取一个有符号16-bit整数值
readUnsignedByte():uint 1 从Socket读取一个无符号字节
readUnsignedInt():uint 2 从Socked读取一个无符号32-bit整数
readUnsignedShort():uint 2 从Socket读取一个无符号16-bit整数
readUTF():String n 从Socket读取一个UTF8字符串
有两个特殊的方法:readBytes()和readUTFBytes();
readBytes()方法只可以让socket读数据但不能返回一个值,并且该方法需要3个参数:
bytes:一个Flash.util.ByteArray实例读取从Socket中收到的数据。
offset:一个uint值,指定从什么位置开始读取socket中收到数据的偏移量,默认值为0
length:一个uint值,用于指定读取bytes的数量,默认值为0,意思就是说将所有的可用的数据都放入ByteArray中。
readUTFBytes()方法,只需要一个长度参数用于指定UTF-8字节的读入数量,并且该方法会将所有读入的字节码转换成为字符串类型。
注意:在从一个Socket读数据之前,首先要判断bytesAvailable的属性,如果你不知道要读入的数据类型是什么就去读数据的话将会产生一个错误(flash.errors.EOFError)。
下面的例子代码连接了一个socket服务器,读取并显示每次从服务器发来的数据。
package{
import flash.display.Sprite;
import flash.events.ProgressEvent;
import flash.net.Socket;
public class SocketExample extends Sprite{
private var socket:Socket;
public function SocketExample(){
socket=new Socket();
socket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);//侦听接收到数据执行的函数
socket.connect("localhost",6666);//连接Socket服务器
}
private function onSocketData(e:ProgressEvent):void{
trace("收到的数据:"+socket.bytesAvailable+"b/s");
//循环读取收到的数据,以字符码显示
while(socket.bytesAvailable){
var data:int=socket.readByte();//读取数据
trace(data);
}
}
}
}
注意:一旦数据从Socket读出,它就不能再次被读,例如:读一个字节之后,这个字节就不能再“放回来”,只能读后边的字节。
当收到的数据为ASCII编码,你可通过readUTFBytes()方法重新构建一个字符串。readUTFBytes()方法需要知道多少个 字节需要转换为字符串,你可以使用bytesAvailable去读所有的字节数据:var string:String=socket.readUTFBytes(socket.bytesAvailable);
XMLSocket实例在从服务器下载完数据后分发数据事件,通过flash.events.DataEvent.DATA常量定义的数据事件包含一个data属性,该属性包含了从服务器收到的信息。
注意:使用XMLSocket从服务器返回的数据总是认为是一个字符串类型的数据。这样不用为任何数据类型的数据指定读取方法。
这些从服务器返回的数据是没有经过任何处理的原始数据,因此,你不能通过XMLSocket连接立即使用XML,你发送和接收的都是纯字符串数据,如果你期望XML,在你处理数据之前,你必须首先将这些数据转换为一个XML的实例。
注意:在data事件分发数据之前,XMLSocket实例必须从服务器收到一个表示为空的byte("\\0");也就是说,从服务器仅仅只发送所需要的字符串是不够的,必须在结尾处加入一个表示为空的byte。
四、同Socket服务器进行握手,并确定收到了什么样的数据和如何处理这些数据。
创建不同的常量来声明协议的状态,使用这些常量将指定的处理函数映射到相应的状态。在一个socketData事件控制器中,通过状态映射调用这些函数的。
建立Socket连接通常要处理握手这个环节,尤其是在服务器初始化需要向客户端发送数据,然后客户端通过一种特殊的方式响应这些数据,接着服务器因此再次响应,整个处理过程直到握手完成并且建立起一个“正常的”连接为止。
处理服务器的不同响应是非常难的,主要的原因是SocketData事件控制器不能保存上下文的顺序,也就是说,服务器的响应不会告诉你“为什 么”响应,也不会告诉你这些响应数据被那个处理程序来处理。要想知道如何处理这些从服务器返回的响应不能从响应的本身来获得,尤其在响应变化的时候,或许 一个响应返回了两个字节码,另一个返回了一个整数值还跟了一个双精度浮点数。
我们通过创建一个状态量来标注不同的上下文,服务器通过这些上下文将数据发送到客户端。与这些状态量都有一个相关联的函数来处理该数据,这样你就可以吃奶 轻松的按照当前的协议状态去调用正确的处理函数。
当你要与一个Socket服务器建立连接需要考虑如下几个步骤:
1、当与服务器连接的时候,服务器立该返回一个标志服务器可以支持的最高协议版本号的整数值。
2、客户端在响应的时候会返回一个实际使用协议的版本号。
3、服务器返回一个8byte的鉴定码。
4、然后客户端将这鉴定码返回到服务器。
5、如果客户端的响应不是服务器端所期望的,或者,就在这个时候该协议变成了一个常规操作模式,于是握手结束。
实现握手框架、你首先要为处理从服务器返回的不同类型的数据分别创建常量。首先,你要从步骤1确定版本号。然后从步骤3收到鉴定码。最后就是步骤5的常规操作模式。我们可以声明如下常量:
public const DETERMINE_VERSION:int=0;
public const RECEIVE_CHALLENGE:int=1;
public const NORMAL:int=2;
常量的值并不重要,重要的是这些值不能有相同的整数值。
下一步我们就要为不同的数据创建不同处理函数了。创建的这三个函数分别被命名为readVersion(),readChallenge()和 readNormalProtocol()。创建完这三个函数后,我们就必须将这三个函数分别映射到前面不同状态常量,从而分别处理在该状态中收到的数 据。代码如下:
stateMap=new Object();
stateMap[DETERMINE_VERSION]=readVersion;
stateMap[RECEIVE_CHALLENGE]=readChallenge;
stateMap[NORMAL]=readNormalProtocol;
最后一步是编写socketData事件处理控制器,只有通过这样的方式,建立在当前协议状态之上的正确的处理函数才可以被调用。首先需要创建一 个currentState的int变量。然后使用stateMap去查询与currentState相关联的函数,这样处理函数就可以被正确调用了。
var processFunc:Function=stateMap[currentState];
processFunc();
下面是前面我们所探讨的握手步骤的完整代码:
package{
import flash.display.Sprite;
import flash.events.ProgressEvent;
import flash.net.Socket;
import flash.utils.ByteArray;
public class SocketExample extends Sprite{
//定义常量
public const DETERMINE_VERSION:int=0;
public const RECEIVE_CHALLENGE:int=1;
public const NORMAL:int=2;
private var stateMap:Object;
private var currentState:int;
private var socket:Socket;
public function SocketExample(){
//初始化stataMap
stateMap=new Object();
stateMap[DETERMINE_VERSION]=readVersion;
stateMap[RECEIVE_CHALLENGE]=readChallenge;
stateMap[NORMAL]=readNormalProtocol;
//初始化currentState
currentState=DETERMINE_VERSION;
//创建Socket连接
socket=new Socket();
socket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);
socket.connect("localhost",6666);
}
private function onSocketData(e:ProgressEvent):void{
var processFunc:Function=stateMap[currentState];
processFunc();
}
private function readVersion():void{
var version:int=socket.readInt();
currentState=RECEIVE_CHALLENGE;
socket.writeInt(version);
socket.flush();
}
private function readChallenge():void{
var bytes:ByteArray=new ByteArray();
socket.readBytes(bytes,0,8);
currentState=NORMAL;
socket.writeBytes(bytes);
socket.flush();
}
private function readNormalProtocol():void{
//空方法
}
}
}
五、与Socket服务器断开,或者当服务器想与你断开的时候发消息给你
通过调用Socket.close()或者XMLSocket.close()方法显性的断开与服务器的连接。同时可以通过监听close事件获得服务器主动断开的消息。
通常情况下我们需要对程序进行下清理工作。比如说,你创建了一个对象,当这个对象没有用的时候我们就要删除它。因此,无论我们什么时候连接一个 Socket服务器,都要在我们完成了必要的任务之后显性的断开连接。一直留着无用的Socket连接浪费网络资源,应该尽量避免这种情况。如果你没有断 开一个连接,那么这个服务器会断续保持着这个无用的连接。这样一来就很快会超过服务器最大Socket连接上线。
Socket和XMLSocket对象断连接的方法是一样的。你只需要调用close()方法就可以了:socket.close();
close()方法用于通知服务器客户端想要断开连接。当服务器主动断开连接会发消息通知客户端。可以通过调用 addEventListener()方法注册一个close事件的监听器。Socket和XMLSocket都是使用Event.CLOSE作为“连接 断开”事件类型的:socket.addEventListener(Event.CLOSE,onClose);
注意:调用close()方法是不会触发close事件的,只有服务器主动发起断开才会触发。一旦一个Socket断开了,就无法读写数据了。如果你想要从新这个连接,你只能再建立一个新的连接了。
六、处理使用Socket时候引发的错误。
使用try/catch处理I/O和EOF错误。
Socket和XMLSocket类对错误的处理很类似。不过,当调用connect()方法的时候,在下面任何一个条件成立的情况下Socket和XMLSocket对象会抛出一个类型为SecurityError的错误。
该.swf未通过本地安全认证
端口号大于65535
当调用XMLSocket对象的send()或者Socket对象的flush()的时候,如果socket还没有连接这两个方法都会抛出一个类 型为IOError的错误。尽管你可以将send()或者flush()方法放入try/catch结构块中,你也不能依赖于try/catch结构块作 为你应用程序的逻辑。更好的办法是,在调用send()或者flush()方法之前使用一个if语句首先判断一下Socket对象的connected属 性是否为True。例如,下面的代码使用了if语句作为程序逻辑的一部分,当Socket对象当前不是连接状态就调用 connectToSocketServer()方法。但是我们依然需要将flush()方法放到try/catch语句块中。通过使用try /catch语句块将flush()方法抛出的错误写入到日志中:
if(socket.connected){
try{
socket.flush();
}catch(error:IOError){
loginstance.write("socket.flush error\n"+error);
}
}else{
connectToSocketServer();
}
所有的Socket类的read方法都能够抛出EOFError和IOError类型的错误。当你试图读一个数据,但是没有任何可用数据将触发EOF错误。当你试图从一个已经关闭的Socket对象中读数据时将会抛出I/O错误。
除了Socket和XMLSocket类的方法能够抛出的错误以外,这些类的对象还会分发错误事件。有两种基本的错误事件类型,他们分别由 socketIOError和securityError错误引起。IOError事件为IOErrorEvent类型,当数据发送或接收失败触发该事 件。SecurityError事件是SecurityErrorEvent类型,当一个Socket尝试连接一个服务器,但由于服务器不在安全沙箱范围 之内或者端口号小于1024的时候触发该错误事件。
注意:这两种安全策略引起的错误都可以通过跨域访问策略文件解决。
1、与Socket服务器建立连接。
2、向Socket服务器发送数据。
3、从Socket服务器读数据。
4、同Socket服务器进行握手,并确定收到了什么样的数据和如何处理这些数据。
5、与Socket服务器断开,或者当服务器想与你断开的时候发消息给你。
6、处理使用Socket时候引发的错误。
实例详解:
一、通过Socket.connect()或者XMLSocket.connect()方法并监听网络连接的事件消息。
连接一台Socket服务器你需要确定两个信息,一个是Socket服务器的域名或者IP地址,另一个是服务器监听的端口号。
无论你使用的是Socket还是XMLSocket类的实例,连接请求都是完全的一样的,两个类都是使用一个名叫connect()的方法,该方法有两个参数:host和port。
host:该参数为字符串类型,可以是一个域名,也可以是一个IP地址。如果Socket服务器与你该Flash影片发布的Web服务器是同一个,该参数为Null。
Port:该参数为一个表示Socket服务器监听端口的Int值,该值最小为1024,除非在服务器中有一个Policy文件用于指定允许端口号小于1024。
因为Flash Socket编程是一个异步的过程,connect() 方法不会等到一个连接完成后再执行下一行代码的执行。如果你想在一个连接完全执行完之前与一个Socket完全绑定,那么你将会得到一个意想不到的结果,并且你当前的代码将不能工作。
在尝试一个新的Socket连接的时候我们最好先添加一个连接事件监听器。当一个连接建立成功,Socket或者XMLSocket会发出一个连接事件,这就可以让你知道交互已经准备好了。
下面举一个Socket实例与本地Socket服务器的6666端口建立连接的例子:
package{
import flash.display.Sprite;
import flash.events.*;
import flash.net.Socket;
public class SocketExample extends Spirte{
private var socket:Socket;
public function SocketExample(){
socket=new Socket();
socket.addEventListener(Event.CONNECT,onConnect);//注册侦听函数
socket.connect("localhost",6666);//连接本地服务器6666端口
}
private function onConnect(e:Event):void{
trace("正在连接服务器...");
}
}
}
如果你想通过XMLSocket与服务器建立连接只需要把上面的Socket换成XMLSocket。
如果连接失败,可能是下面两种原因:一种是连接立即失败和运行时错误,另一种是如果无法完成连接从而产生一个ioError或者securityError事件。
请牢记,当与一个主机建立一个Socket连接时,Flash Player要遵守如下安全沙箱规则:
1、Flash的.swf文件和主机必须严格的在同一个域名,只有这样才可以成功建立连接。
2、一个从网上发布的.swf文件是不可以访问本地服务器的。
3、本地未通过认证的.swf文件是不可以访问任何网络资源的。
4、你想跨域访问或者连接低于1024的端口,必须使用一个跨域策略文件。
如果尝试连接未认证的域或者低端口服务,这样就违反了安全沙箱策略,同时会产生一个securityError事件。这些情况都可以通过一个跨域 策略文件解决,无论是Socket对象还是XMLSocket对象的策略文件,都必须在连接之前通过使用 flash.system.Security.loadPolicyFile()方法载入策略文件,具体如 下:Security.loadPolictyFile("http://www.example.cn/crossdomain.xml");
二、向Socket服务器发送数据。
对于Socket对象来说,通过用write方法(writeByte(),writeUTFBytes()等方法),先向缓存区写入数据,然后使用flush()方法发送数据,对于XMLSocket对象,使用send()方法。
当你使用Socket对象向服务器发送数据的时候,你首先要将数据写入到一个缓冲区中。Socket类设置了一系列的方法来写数据。每一个方法都 用于写不同的数据类型的数据,这些方法分别 是:writeBoolean(),writeByte(),writeBytes(),writeDouble(),writeFloat(),writeInt(),writeMultiByte(),writeObject(),writeShort(),writeUnsignedInt(),writeUTF() 和writeUTFBytes()。这些方法大多数都只接受一个参数,该参数的类型同方法的名字相匹配。例如:writeBoolean()方法接受一个 布尔值作为参数,而 writeByte(),writeDouble(),writeFloat(),writeInt(),writeShort(),writeUnsignedInt() 方法接受一个数字型参数。writeObject()方法接受一个对象类型作为参数。但该对象必须序列化成为AMF格式。writeBytes()方法允 许你传一个ByteArray参数,并带有偏移量和长度两个参数。例如,下面这段代码,调用了一个writeBytes()方法,该方法将 ByteArray对象中的所有byte值都传出 去:socket.writeBytes(byteArray,0,byteArray.length);
writeUTF()和writeUTFBytes()方法允许你的发送字符串类型的参数。每一个方法只接受一个字符串作为参数。 writeUTFBytes()方法简单的将字符串作为Bytes发送。writeUTF()方法在写入真正数据之前,先写入bytes的数量。
writeMultiByte()方法也允许字符串类型的参数,但是使用的为非默认字符集。该方法需要两个参数:字符串和字符集名称。在 Flash和Flex的帮助文档中有一个自持所有字符集的列表,该列表中的标签和描述符是--对应的,使用标签值作为writeMultiByte()作 为字符集。例如下面的代码发送一个编码为Unicode的字符 串:socket.writeMultiByte("example","unicode");
向一个Socket对象传数值的方法完全依赖于你所有数据的类型和服务所接受数据的类型,使用一个Socket对象,你完全可以使用 ActionScript写一个Telnet和POP mail客户端,这两种协议都支持ASCII字符指令。例如:在连接一个POP服务器之后,你可通过使用USER指令指定一个用户,下面代码向一个 Socket对象发一条指令:socket.writeUTFBytes("USER exampleUsername\n");
向一个Socket对象写入数据其实并没有将数据发送到Socket服务器。每调用一个write方法都向Socket对象添加一个数据。当你想 将这些累积的数据发送到Socket服务器需要调用flush()方法,flush()方法调用之后将把所有已经写入的数据发送出去,并清空缓冲 区:socket.flush();
XMLSocket类是一个非常简单用于发送数据的API,写于发数据都是由send()这一方法来完成。send()方法可以接受任何数据类型 的参数,它可以将所有的参数都转换为一个字符串类型并发送到服务器,通常参数为一个XML对象或者一个包含数据结构类似XML数据的字符 串:xmlSocket.send();
然后,准备的格式完全依赖于服务器所能够接受的格式。如果服务器接受XML格式的数据,你必须发送XML格式的数据。如果服务器只接受URL编码的数据,你也必须发送URL编码的数据。
三、从Socket服务器读数据
对于Socket实例,先收到socketData事件,然后调用如下两个方法的一个,比如:readByte()或者readInt(),在事件控制器吕确定不会去读过去的bytesAvailable.
对于XMLSocket实例,先收到data事件,然后解析从事件控制器内部装载的XML数据。
socket在Flash中是一个异步的行为,因此,它就不能简单的创建一个Socket连接,然后就立该尝试去读取数据。read方法不能等到 从服务器传过来数据之后在返回。换句话说,你只能在客户端从服务器载入所有数据之后才可以读取数据。在数据可用之前读数据会产生一个错误。
通过socketData事件广播到Socket实例,这样我们就可以知道什么时候数据可以被读取。那么我们要为socketData事件添加一 个事件监听器,任何时候只要有新的数据从一个socket服务器发送过来,都会触发事件控制器。在事件处理器的内部我们写入我们要执行的代码去读取和处理 收到的数据。
从一个前端服务器读取数据,Socket类为我们提供了许多不同的方法,这些方法依赖于你所读得数据类型。例如,你可以通过readByte() 方法读一个byte()数据,或者通过一个使用readUnsignedInt()方法去读一个无符号整数。下面这个表列出来能够从服务器读取的数据类 型,返回值和read方法每次读入的字节数。
方法:返回值类型 字节数 描述
readBoolean():Boolean 1 从Socket读取一个Boolean值
readByte():int 1 从Socket读取一个Byte值
readDouble():Number 8 从Socket读取一个IEEE 754双精度浮点数
readFloat():Number 4 从Socket读取一个IEEE 754单精度浮点数
readInt():int 4 从Socket读取一个有符号32-bit整数值
readObject():* n 从Socket读取一个AMF-encoded对象
readShort():int 2 从Socket读取一个有符号16-bit整数值
readUnsignedByte():uint 1 从Socket读取一个无符号字节
readUnsignedInt():uint 2 从Socked读取一个无符号32-bit整数
readUnsignedShort():uint 2 从Socket读取一个无符号16-bit整数
readUTF():String n 从Socket读取一个UTF8字符串
有两个特殊的方法:readBytes()和readUTFBytes();
readBytes()方法只可以让socket读数据但不能返回一个值,并且该方法需要3个参数:
bytes:一个Flash.util.ByteArray实例读取从Socket中收到的数据。
offset:一个uint值,指定从什么位置开始读取socket中收到数据的偏移量,默认值为0
length:一个uint值,用于指定读取bytes的数量,默认值为0,意思就是说将所有的可用的数据都放入ByteArray中。
readUTFBytes()方法,只需要一个长度参数用于指定UTF-8字节的读入数量,并且该方法会将所有读入的字节码转换成为字符串类型。
注意:在从一个Socket读数据之前,首先要判断bytesAvailable的属性,如果你不知道要读入的数据类型是什么就去读数据的话将会产生一个错误(flash.errors.EOFError)。
下面的例子代码连接了一个socket服务器,读取并显示每次从服务器发来的数据。
package{
import flash.display.Sprite;
import flash.events.ProgressEvent;
import flash.net.Socket;
public class SocketExample extends Sprite{
private var socket:Socket;
public function SocketExample(){
socket=new Socket();
socket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);//侦听接收到数据执行的函数
socket.connect("localhost",6666);//连接Socket服务器
}
private function onSocketData(e:ProgressEvent):void{
trace("收到的数据:"+socket.bytesAvailable+"b/s");
//循环读取收到的数据,以字符码显示
while(socket.bytesAvailable){
var data:int=socket.readByte();//读取数据
trace(data);
}
}
}
}
注意:一旦数据从Socket读出,它就不能再次被读,例如:读一个字节之后,这个字节就不能再“放回来”,只能读后边的字节。
当收到的数据为ASCII编码,你可通过readUTFBytes()方法重新构建一个字符串。readUTFBytes()方法需要知道多少个 字节需要转换为字符串,你可以使用bytesAvailable去读所有的字节数据:var string:String=socket.readUTFBytes(socket.bytesAvailable);
XMLSocket实例在从服务器下载完数据后分发数据事件,通过flash.events.DataEvent.DATA常量定义的数据事件包含一个data属性,该属性包含了从服务器收到的信息。
注意:使用XMLSocket从服务器返回的数据总是认为是一个字符串类型的数据。这样不用为任何数据类型的数据指定读取方法。
这些从服务器返回的数据是没有经过任何处理的原始数据,因此,你不能通过XMLSocket连接立即使用XML,你发送和接收的都是纯字符串数据,如果你期望XML,在你处理数据之前,你必须首先将这些数据转换为一个XML的实例。
注意:在data事件分发数据之前,XMLSocket实例必须从服务器收到一个表示为空的byte("\\0");也就是说,从服务器仅仅只发送所需要的字符串是不够的,必须在结尾处加入一个表示为空的byte。
四、同Socket服务器进行握手,并确定收到了什么样的数据和如何处理这些数据。
创建不同的常量来声明协议的状态,使用这些常量将指定的处理函数映射到相应的状态。在一个socketData事件控制器中,通过状态映射调用这些函数的。
建立Socket连接通常要处理握手这个环节,尤其是在服务器初始化需要向客户端发送数据,然后客户端通过一种特殊的方式响应这些数据,接着服务器因此再次响应,整个处理过程直到握手完成并且建立起一个“正常的”连接为止。
处理服务器的不同响应是非常难的,主要的原因是SocketData事件控制器不能保存上下文的顺序,也就是说,服务器的响应不会告诉你“为什 么”响应,也不会告诉你这些响应数据被那个处理程序来处理。要想知道如何处理这些从服务器返回的响应不能从响应的本身来获得,尤其在响应变化的时候,或许 一个响应返回了两个字节码,另一个返回了一个整数值还跟了一个双精度浮点数。
我们通过创建一个状态量来标注不同的上下文,服务器通过这些上下文将数据发送到客户端。与这些状态量都有一个相关联的函数来处理该数据,这样你就可以吃奶 轻松的按照当前的协议状态去调用正确的处理函数。
当你要与一个Socket服务器建立连接需要考虑如下几个步骤:
1、当与服务器连接的时候,服务器立该返回一个标志服务器可以支持的最高协议版本号的整数值。
2、客户端在响应的时候会返回一个实际使用协议的版本号。
3、服务器返回一个8byte的鉴定码。
4、然后客户端将这鉴定码返回到服务器。
5、如果客户端的响应不是服务器端所期望的,或者,就在这个时候该协议变成了一个常规操作模式,于是握手结束。
实现握手框架、你首先要为处理从服务器返回的不同类型的数据分别创建常量。首先,你要从步骤1确定版本号。然后从步骤3收到鉴定码。最后就是步骤5的常规操作模式。我们可以声明如下常量:
public const DETERMINE_VERSION:int=0;
public const RECEIVE_CHALLENGE:int=1;
public const NORMAL:int=2;
常量的值并不重要,重要的是这些值不能有相同的整数值。
下一步我们就要为不同的数据创建不同处理函数了。创建的这三个函数分别被命名为readVersion(),readChallenge()和 readNormalProtocol()。创建完这三个函数后,我们就必须将这三个函数分别映射到前面不同状态常量,从而分别处理在该状态中收到的数 据。代码如下:
stateMap=new Object();
stateMap[DETERMINE_VERSION]=readVersion;
stateMap[RECEIVE_CHALLENGE]=readChallenge;
stateMap[NORMAL]=readNormalProtocol;
最后一步是编写socketData事件处理控制器,只有通过这样的方式,建立在当前协议状态之上的正确的处理函数才可以被调用。首先需要创建一 个currentState的int变量。然后使用stateMap去查询与currentState相关联的函数,这样处理函数就可以被正确调用了。
var processFunc:Function=stateMap[currentState];
processFunc();
下面是前面我们所探讨的握手步骤的完整代码:
package{
import flash.display.Sprite;
import flash.events.ProgressEvent;
import flash.net.Socket;
import flash.utils.ByteArray;
public class SocketExample extends Sprite{
//定义常量
public const DETERMINE_VERSION:int=0;
public const RECEIVE_CHALLENGE:int=1;
public const NORMAL:int=2;
private var stateMap:Object;
private var currentState:int;
private var socket:Socket;
public function SocketExample(){
//初始化stataMap
stateMap=new Object();
stateMap[DETERMINE_VERSION]=readVersion;
stateMap[RECEIVE_CHALLENGE]=readChallenge;
stateMap[NORMAL]=readNormalProtocol;
//初始化currentState
currentState=DETERMINE_VERSION;
//创建Socket连接
socket=new Socket();
socket.addEventListener(ProgressEvent.SOCKET_DATA,onSocketData);
socket.connect("localhost",6666);
}
private function onSocketData(e:ProgressEvent):void{
var processFunc:Function=stateMap[currentState];
processFunc();
}
private function readVersion():void{
var version:int=socket.readInt();
currentState=RECEIVE_CHALLENGE;
socket.writeInt(version);
socket.flush();
}
private function readChallenge():void{
var bytes:ByteArray=new ByteArray();
socket.readBytes(bytes,0,8);
currentState=NORMAL;
socket.writeBytes(bytes);
socket.flush();
}
private function readNormalProtocol():void{
//空方法
}
}
}
五、与Socket服务器断开,或者当服务器想与你断开的时候发消息给你
通过调用Socket.close()或者XMLSocket.close()方法显性的断开与服务器的连接。同时可以通过监听close事件获得服务器主动断开的消息。
通常情况下我们需要对程序进行下清理工作。比如说,你创建了一个对象,当这个对象没有用的时候我们就要删除它。因此,无论我们什么时候连接一个 Socket服务器,都要在我们完成了必要的任务之后显性的断开连接。一直留着无用的Socket连接浪费网络资源,应该尽量避免这种情况。如果你没有断 开一个连接,那么这个服务器会断续保持着这个无用的连接。这样一来就很快会超过服务器最大Socket连接上线。
Socket和XMLSocket对象断连接的方法是一样的。你只需要调用close()方法就可以了:socket.close();
close()方法用于通知服务器客户端想要断开连接。当服务器主动断开连接会发消息通知客户端。可以通过调用 addEventListener()方法注册一个close事件的监听器。Socket和XMLSocket都是使用Event.CLOSE作为“连接 断开”事件类型的:socket.addEventListener(Event.CLOSE,onClose);
注意:调用close()方法是不会触发close事件的,只有服务器主动发起断开才会触发。一旦一个Socket断开了,就无法读写数据了。如果你想要从新这个连接,你只能再建立一个新的连接了。
六、处理使用Socket时候引发的错误。
使用try/catch处理I/O和EOF错误。
Socket和XMLSocket类对错误的处理很类似。不过,当调用connect()方法的时候,在下面任何一个条件成立的情况下Socket和XMLSocket对象会抛出一个类型为SecurityError的错误。
该.swf未通过本地安全认证
端口号大于65535
当调用XMLSocket对象的send()或者Socket对象的flush()的时候,如果socket还没有连接这两个方法都会抛出一个类 型为IOError的错误。尽管你可以将send()或者flush()方法放入try/catch结构块中,你也不能依赖于try/catch结构块作 为你应用程序的逻辑。更好的办法是,在调用send()或者flush()方法之前使用一个if语句首先判断一下Socket对象的connected属 性是否为True。例如,下面的代码使用了if语句作为程序逻辑的一部分,当Socket对象当前不是连接状态就调用 connectToSocketServer()方法。但是我们依然需要将flush()方法放到try/catch语句块中。通过使用try /catch语句块将flush()方法抛出的错误写入到日志中:
if(socket.connected){
try{
socket.flush();
}catch(error:IOError){
loginstance.write("socket.flush error\n"+error);
}
}else{
connectToSocketServer();
}
所有的Socket类的read方法都能够抛出EOFError和IOError类型的错误。当你试图读一个数据,但是没有任何可用数据将触发EOF错误。当你试图从一个已经关闭的Socket对象中读数据时将会抛出I/O错误。
除了Socket和XMLSocket类的方法能够抛出的错误以外,这些类的对象还会分发错误事件。有两种基本的错误事件类型,他们分别由 socketIOError和securityError错误引起。IOError事件为IOErrorEvent类型,当数据发送或接收失败触发该事 件。SecurityError事件是SecurityErrorEvent类型,当一个Socket尝试连接一个服务器,但由于服务器不在安全沙箱范围 之内或者端口号小于1024的时候触发该错误事件。
注意:这两种安全策略引起的错误都可以通过跨域访问策略文件解决。
发表评论
-
Flex小记录
2011-02-24 10:18 1288Flex读取XML: <mx:HTTPServic ... -
flex实现滑动显示隐藏效果
2010-12-30 15:30 1592鼠标划过的时候显示菜单栏 ,鼠标移开后隐藏菜单栏。比较常用 ... -
flex DataTimePicker时间控件
2010-12-27 11:54 1312两种DatatimePicker: 1.Datatim ... -
ActionScript 生成伪Guid
2010-12-24 09:52 1202在一个Flash制作的图片上传程序中(使用了FileRefer ... -
Flex中Image组件怎么才能非等比例拉伸图片
2010-12-23 15:49 1504Image组件怎么才能非等比例拉伸图片 设 ... -
Flex中Accordion用法
2010-12-23 11:45 3077<? xml version = & ... -
Flex(替代session过期)实现用户长时间不操作要求重新登录的处理
2010-12-23 11:08 1501flex(替代session过期)用户长时间不操作要求重新登录 ... -
12个简单易用的flex函数
2010-12-21 10:10 11311.拷贝内容到剪贴板: ... -
Flex自定义控件——Pagebar分页控件
2010-12-20 09:41 5255开发时经常遇到用一个DataGrid分页显示 ... -
Flex资源,很全,很牛!
2010-12-20 09:30 14581、as3ebaylib http://code ... -
Flex 窗体 最大化、最小化实例
2010-12-20 09:28 2710---导入flexMdi.swc (http ... -
在Flex中复制文字到操作系统的剪贴板
2010-12-15 11:18 1233这个实例演示了怎么样使用System. ... -
Flex让Slider控件拖动时显示Tooltip
2010-12-14 16:10 1904格式化与自定义Slider中显示的Tooltip ... -
Flex给Alert加个Icon
2010-12-14 16:05 1279给Alert加个Icon 很简单只要先 Embed 一 ... -
在Flex中用Validator验证数字、字符串、Email、电话号码等
2010-12-14 09:54 4311mx.validators ... -
Flex中使用FileReference类下载文件
2010-12-14 09:47 1790下面的实例演示了Flex中的 File ... -
Flex使用ArrayCollection的filterFunction属性过滤DataGrid
2010-12-14 09:42 1796下面的实例演示了在Flex中怎样使用 ... -
Flex 树形控件(Tree )的使用
2010-12-13 16:24 3471一、树形控件的常用属性 1、dragMoveE ... -
FLEX3中应用CSS完全详解手册(下)
2010-12-13 11:40 877myTabs中的设置 cornerRadiusTab ... -
FLEX3中应用CSS完全详解手册(上)
2010-12-13 11:16 897编辑完这个FLEX下的CSS说明后,我基本已经兵临崩溃 ...
相关推荐
【ActionScript3.0 Socket编程】是Flash平台中进行低级网络通信的一种方式,它允许开发者直接与服务器进行双向的二进制数据交换。在ActionScript3.0中,Socket编程涉及以下几个关键步骤: 1. **与Socket服务器建立...
7. **网络通信**:多人在线游戏需要与服务器进行数据交换,ActionScript 3.0的Socket和XMLSocket类支持TCP和UDP通信。 8. **资源管理**:游戏往往包含大量的图片、音频和XML数据,使用Loader类可以加载和管理这些...
ActionScript 3.0提供了XML、JSON和Socket等接口,使得游戏能够与其他服务器或设备进行数据交换。 最后,书中会讨论游戏设计的最佳实践和优化技巧,帮助开发者提升游戏性能,减少内存消耗,以及如何调试和测试游戏...
ActionScript 3.0是Adobe开发的一种面向对象的编程语言,主要用于创建富互联网应用程序(RIA),尤其是Flash平台上的游戏和交互式内容。本资源合集包含ActionScript 3.0游戏编程的第1版和第2版,为学习者提供了丰富...
你将学习如何使用ActionScript 3.0的Socket和URLLoader类来实现网络通信,从而创建多人协作或竞技的游戏模式。 在实践部分,本书可能会包含多个逐步指导的示例项目,帮助读者将所学知识应用到实际游戏开发中。这些...
根据给定文件中的标题、描述、标签以及部分内容,本文将详细介绍有关ActionScript 3.0 (AS3) 中Socket编程的基础知识与应用实践。 ### 一、ActionScript 3.0 Socket简介 #### 1. Socket概念 在ActionScript 3.0中...
Flash AS3.0 中的 Socket 编程是使用 ActionScript 3.0 进行网络编程的一种方式。它允许 Flash 应用程序与服务器之间建立连接,以便进行数据交换。下面是关于 Flash AS3.0 Socket 编程的重要知识点: 1. 与 Socket ...
这份"ActionScript3.0编程手册PDF"提供了全面的指南,帮助开发者深入理解和熟练运用ActionScript3.0。 一、ActionScript3.0概述 ActionScript3.0相较于之前的版本有显著的提升,特别是在性能、类型系统和编程模型...
这个压缩包文件《点睛:ActionScript3.0游戏互动编程》源文件,包含了丰富的游戏编程资源,是学习和探索AS3游戏开发的宝贵资料。 在ActionScript3.0中,游戏互动编程主要涉及以下几个核心知识点: 1. **面向对象...
1. **网络通信**:ActionScript 3.0中的`Flash.Net.Socket`类或者`flash.net.XMLSocket`类可以用来实现客户端与服务器之间的双向通信。通过建立TCP或HTTP连接,客户端可以发送和接收消息。 2. **数据传输格式**:...
《ActionScript 3.0编程精髓》一书深入探讨了ActionScript 3.0这一强大的脚本语言,它是Adobe Flash平台的核心组成部分,广泛应用于动画、交互式内容和Web应用程序的开发。以下是从这本书中提炼出的关键知识点: ##...
ActionScript3.0是Adobe开发的一种面向对象的编程语言,主要用于创建富互联网应用程序(RIA),尤其是在Flash平台上。它是Flash Professional、Flash Builder等工具的核心组成部分,让开发者能够为网页、桌面和移动...
在解压后的“ActionScript3.0chm完整版”文件中,你将找到详细的API参考、教程和示例代码,这些都能帮助你掌握ActionScript 3.0的核心概念和技术。无论是学习基本语法、类库使用,还是深入到高级特性,这个文档都是...
《ActionScript 3.0 游戏编程大学》是一本专为游戏开发爱好者和专业人士设计的教程,旨在深入讲解如何使用ActionScript 3.0这一强大的脚本语言创建丰富的交互式游戏。ActionScript 3.0是Adobe Flash Platform的核心...
《ActionScript3.0语言和组件参考》是Adobe官方发布的一份权威指南,主要针对ActionScript3.0这一编程语言及其相关组件进行详尽的解释和说明。该文档以CHM(Compiled HTML Help)格式呈现,便于用户快速查找和浏览所...
ActionScript3.0(简称AS3)是Adobe Flash平台的核心编程语言,用于创建富媒体内容、交互式应用程序和游戏。这个压缩包包含了多个章节的源文件,覆盖了ActionScript3.0游戏互动编程的关键知识点。以下是对每个章节的...
### ActionScript 3.0编程精髓(包括处理视频) #### 一、ActionScript 3.0简介 ActionScript 3.0是一种强大的面向对象的编程语言,主要用于开发交互式应用程序和游戏,尤其适用于Adobe Flash Player和Adobe AIR环境...
《Flash ActionScript 3.0 语言和组件参考》是一份详尽的指南,专为开发者提供关于在Flash环境中使用ActionScript 3.0进行编程的深入知识。ActionScript是Adobe Flash平台的核心脚本语言,它允许创建动态交互的内容...
ActionScript 3.0是Adobe开发的一种编程语言,主要用于创建富互联网应用程序(RIA),特别是Flash平台上的交互式内容。这个入门基础教程旨在帮助初学者掌握ActionScript 3.0的基本概念和语法,以便在Web开发领域中...