`
#天琪#
  • 浏览: 155680 次
  • 性别: Icon_minigender_2
  • 来自: 长沙
社区版块
存档分类
最新评论

关于Socket

    博客分类:
  • AS3
阅读更多
1.ProgressEvent
    开始加载操作或套接字已接收到数据后,Flash ® Player 将调度 ProgressEvent 对象。 这些事件通常在将 SWF 文件、图像或数据加载到 Flash Player 中时生成。 有两种类型的进程事件:ProgressEvent.PROGRESS 和 ProgressEvent.SOCKET_DATA。

   DataEvent事件
   将原始数据完全加载到 Flash Player 后,Flash® Player 将调度 DataEvent 对象。 存在两种数据事件类型:
DataEvent.DATA:针对发送或接收的数据进行调度。
DataEvent.UPLOAD_COMPLETE_DATA:当数据已发送且服务器响应后进行调度。


2.与Socket服务器建立连接.
解决方法:
    我们通过调用Socket.connect( )或者XMLSocket.connect( )方法并监听网络连接的事件消息.
讨论:
    连接一台Socket服务器你需要确定两个信息,一个是Socket服务器的域名或者IP地址,另一个是服务器监听的端口号.
    无论你使用的是Socket还是XMLSocket类的实例,连接请求都是完全的一样的,两个类都是使用一个名叫connect()的方法,该方法有两个参数:
CODE:

host :
该参数为字符串类型,可以是一个域名,例如"www.example.com",也可以是一个IP地址,例如"192.168.1.101".如果Socket服务器与你该Flash影片发布的Web服务器是同一个,该参数为Null.
CODE:

port :
该参数为一个表示Socket服务器监听端口的int值.该值最小为1024.除非在服务器中有一个policy文件,用于指定允许端口号小于1024.
    因为Flash Socket编程是一个异步的过程,connect()方法不会等到一个连接完成后再执行下一行代码的执行.如果你想在一个连接完全执行完之前与一个Socket完全绑定,那么你将会得到一个意想不到的结果,并且你当前的代码将不能工作.
    在尝试一个新的Socket连接的时候我们最好先添加一个连接事件监视器.当一个连接建立成功,Socket或者XMLSocket会发出一个连接事件,这就可以让你知道交互已经准备好了.
    下面举了一个Socket实例与本地Socket服务器的2900端口建立连接的例子:
CODE:

package {
  import flash.display.Sprite;
  import flash.events.*;
  import flash.net.Socket;
  public class SocketExample extends Sprite {
    private var socket:Socket;
    public function SocketExample(  ) {
      socket = new Socket(  );
    
      // Add an event listener to be notified when the connection
      // is made
      socket.addEventListener( Event.CONNECT, onConnect );
    
      // Connect to the server
      socket.connect( "localhost", 2900 );
    }
  
    private function onConnect( event:Event ):void {
      trace( "The socket is now connected..." );
    }
  
  }
}
如果你想通过XMLSocket与服务器建立连接代码也是基本一样的.首先你创建了一个连接事件监视器,然后调用connect()方法.所不同的是Socket实例改为了XMLSocket;

如果连接失败,可那是下面两种原因的一种:一种是连接立即失败和运行时错误,另一种是如果无法完成连接从而产生一个ioError或者securityError事件.关于错误事件处理信息的描述,我们打算改日讨论.
    请牢记,当与一个主机建立一个Socket连接时,Flash Player要遵守如下安全沙箱规则.
    1.Flash的.swf文件和主机必须严格的在同一个域名,只有这样才可以成功建立连接.
    2.一个从网上发布的.swf文件是不可以访问本地服务器的.
    3.本地未通过认证的.swf文件是不可以访问任何网络资源的.
    4.你想跨域访问或者连接低于1024的端口,必须使用一个跨域策略文件.
    如果尝试连接未认证的域或者低端口服务,这样就违反了安全沙箱策略,同时会产生一个securityError事件.这些情况都可以通过使用一个跨域策略文件解决.无论是Socket对象还是XMLSocket对象的策略文件,都必须在连接之前通过使用 flash.system.Security.loadPolicyFile()方法载入策略文件.具体如下:
    Security.loadPolicyFile("http://www.rightactionscript.com/crossdomain.xml");
    获得的改策略文件不仅定义了允许的域名,还定义了端口号.如果你不设置端口号,那么Flash Player默认为80端口(HTTP协议默认端口).在<allow-access-from>标签中可以使用逗号隔开设置多个端口号.下面这个例子就是允许访问80和110端口.


3.2.向Socket服务器发送数据.
解决方法:
    对于Socket对象来说,通过是用write方法(writeByte(),writeUTFBytes( )等方法.)先向缓存区写入数据,然后使用flush()方法发送数据.对于XMLSocket对象,使用send()方法.
讨论:
    Socket和XMLSocket类向Socket服务器发送数据的方法是不相同的.让我们首先看一下Socket类的方法.
    当你使用Socket对象向服务器发送数据的时候,你首先要将数据写入到一个缓冲区中.Socket类设置了一系列的方法来写数据.每一个方法都用于写不同的数据类型的数据(或者不同的数据).这些方法分别是: writeBoolean( ), writeByte( ), writeBytes( ), writeDouble( ), writeFloat( ), writeInt( ), writeMultiByte( ), writeObject( ), writeShort( ), write- UnsignedInt( ), writeUTF(), 和writeUTFBytes( ). 这些方法大多数都只接受一个参数,该参数的类型同方法的名字相匹配.例如,writeBoolean()方法接受一个布尔值作为参数,而 writeByte( ), writeDouble( ), writeFloat( ), writeInt( ), writeShort( ), writeUnsignedInt( ) 方法接受一个数字型参数.writeObject()方法接受一个对象类型作为参数,但该对象必须序列化成为AMF格式.writeBytes( )方法允许你传一个ByteArray参数,并带有偏移量和长度两个参数.例如,下面这段代码,调用了一个writeBytes( )方法,该方法将ByteArray对象中的所有byt值都传出去了(偏移量为0,长度和ByteArray数组长度等长):
CODE:

socket.writeBytes(byteArray, 0, byteArray.length);
writeUTF( )和writeUTFBytes( ) 方法允许你的发送字符串类型的参数.每个一个方法只接受一个字符串作为参数.writeUTFBytes( )方法简单的将字符串作为Bytes发送.writeUTF( )方法在写入真正数据之前,先写入byts的数量.
    writeMultiByte( )方法也允许字符串类型的参数,但是使用的为非默认字符集.该方法需要两个参数:字符串和字符集名称.在Flash和Flex的帮助文档中有一个自持所有字符集的列表,该列表中的标签和描述符是一一对应的.使用标签值作为writeMultiByte( )作为字符集.例如下面的代码发送了一个编码为Unicode的字符串:
CODE:

socket.writeMultiByte("example", "unicode");
相一个Socket对象传数值的方法完全依赖于你所有数据的类型和服务所接受数据的类型.使用一个Socket对象,你完全可以使用 ActionScript写一个Telnet和POP mail客户端.这两种协议都支持ASCII字符指令.例如,在连接一个POP服务器之后,你可以通过使用USER指令指定一个用户.下面代码向一个 Socket对象发一条指令:
CODE:

// POP servers expect a newline (\n) to execute the preceding command.
socket.writeUTFBytes("USER exampleUsername\n");
向一个Socket对象写入数据其实并没有将数据发送到Socket服务器.每调用一个write方法都向Socket对象添加一个数据.例如,下面代码向一个Socket对象添加了四个byte的数据,但是没有一个发出了.
CODE:

socket.writeByte(1);
socket.writeByte(5);
socket.writeByte(4);
socket.writeByte(8);
当你想将这些累积的数据发送到Socket服务器需要调用flush()方法.flush()方法调用之后将把所有已经写入的数据发送出去,并清空缓冲区:
CODE:

socket.flush(  );
XMLSocket类是一个非常简单用于发送数据的API.写于发数据都是由send()这一个方法来完成的.send()方法可以接受任何数据类型的参数.它可以将所有的参数都转换为一个字符串类型并发送到服务器.通常参数为一个XML对象或者一个包含数据结构类似XML数据的字符串:
CODE:

xmlSocket.send(xml);
然而,准确的格式完全依赖于服务器所能够接受的格式.如果服务器接受XML格式的数据,你必须发送XML格式的数据.如果服务器只接受URL编码的数据,你也必须发送URL编码的数据.



4.从Socket服务器读数据
解决方法:
    对于Socket实例,先收到socketData事件,然后调用如下两个方法的一个,比如,readByte()或者readInt(),在事件控制器中确定不会去读过去的bytesAvailable.
    对于XMLSocket实例,先收到data事件,然后解析从事件控制器内部装载的XML数据.
讨论:
    从一个socket连接接收的数据依赖于你使用的Socket的类型.socket和XMLSocket都可以从服务器接受到数据,但是它们处于不同重量级的技术.让我们在讨论XMLSocket之前先关注下Socket类.
    我都知道socket在Flash中是一个异步的行为.因此,它就不能简单的创建一个Socket连接,然后就立刻尝试去读取数据.read方法不能等到从服务器传过来数据之后在返回.换句话说,你只能在客户端从服务器载入所有数据之后才可以读取数据.在数据可用之前读数据会产生一个错误.
    通过socketData事件广播到Socket实例,这样我们就可以知道什么时候数据可以被读取.那么我们要为socketData事件添加一个事件监视器,任何时候只要有新的数据从一个socket服务器发送过来,都会触发事件控制器.在事件处理器的内部我们写入我们要执行的代码去读取和处理收到的数据.
    从一个前端服务器读取数据,Socket类为我们提供了许多不同的方法,这些方法依赖于你所读得数据类型.例如,你可以通过readByte()方法读一个byte数据,或者通过一个使用readUnsignedInt()方法去读一个无符号整数.下面这个表列出来能够从服务器读取的数据类型,返回值,和 read方法每次读入的字节数.
QUOTE:

Table:Socket read methods for various datatypes
方法:返回值类型         描述         字节数
readBoolean( ):Boolean         从Socket读取一个Boolean值.         1
readByte( ):int         从Socket读取一个byte值.         1
readDouble( ):Number         从Socket读取一个IEEE 754双精度浮点数.         8
readFloat( ):Number         从Socket读取一个IEEE 754单精度浮点数.         4
readInt( ):int         从Socket读取一个有符号32-bit整数值.         4
readObject( ):*         从Socket读取一个AMF-encoded对象.         n
readShort( ):int         从Socket读取一个有符号16-bit整数值.         2
readUnsignedByte( ):uint         从Socket读取一个无符号字节.         1
readUnsignedInt( ):uint         从Socket读取一个无符号32-bit整数         4
readUnsignedShort( ):uint         从Socket读取一个无符号16-bit整数.         2
readUTF( ):String         从Socket读取一个一个UTF8字符串.         n
有两个额外的方法没有在上面这个表中描述.它们分别是readBytes()和readUTFBytes().readBytes()方法只可以让socket读数据但不能返回一个值,并且该方法需要3个参数:
CODE:

bytes:
一个flash.util.ByteArray实例读取从socket中收到的数据.
CODE:

offset:
一个uint值,指定从什么位置开始读取socket中收到数据的偏移量.默认值为0.
CODE:

length:
一个uint值,用于指定读取bytes的数量.默认值为0,意思就是说将所有的可用的数据都放入ByteArray中.
    另一个readUTFBytes()方法,只需要一个长度参数用于指定UTF-8字节的读入数量,并且该方法会将所有读入的字节码转换成为字符串类型.
注意:在从一个Socket读数据之前,首先要判断bytesAvailable的属性.如果你不知道要读入的数据类型是什么就去读数据的话,将会产生一个错误(flash.errors.EOFError).
    下面的例子代码连接了一个socket服务器,读取并显示每次从服务器发来的数据.
CODE:


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(  );
    
      // Listen for when data is received from the socket server
      socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
      // Connect to the server
      socket.connect( "localhost", 2900 );
    }
    private function onSocketData( eventrogressEvent ):void {
      trace( "Socket received " + socket.bytesAvailable + " byte(s) of data:" );
      // Loop over all of the received data, and only read a byte if there
      // is one available
      while ( socket.bytesAvailable ) {
        // Read a byte from the socket and display it
        var data:int = socket.readByte(  );
        trace( data );
      }
    }
  }
}
在上面的这个例子中,如果一个socket服务器发送回一个消息(例如"hello"),当一个客户段连入服务器就会返回并输出下面类似的文字:
CODE:

Socket received 5 byte(s) of data:
72
101
108
108
111
注意:一旦数据从socket读出,它就不能再次被读.例如,读一个字节之后,这个字节就不能再"放回来",只能读后边的字节.
    当收到的数据为ASCII编码,你可以通过readUTFBytes()方法重新构建一个字符串.readUTFBytes()方法需要知道多少个字节需要转换为字符串.你可以使用bytesAvailable去读所有的字节数据:
var string:String = socket.readUTFBytes(socket.bytesAvailable);
    XMLSocket类的动作和Socket类相比在从服务器接受数据的风格相似.两者都是通过事件监视器来监听数据接收通知的,这主要取决于Flash异步的Socket实现.然而,在处理实际数据的时候有很大的不同.
    有个XMLSocket实例在从服务器下载完数据后分发数据事件.通过flash.events.DataEvent.DATA常量定义的数据事件包含一个data属性,该属性包含了从服务器收到的信息.
注意:使用XMLSocket从服务器返回的数据总是认为是一个字符串类型的数据.这样不用为任何数据类型的数据指定读取方法.
    这些从服务器返回的数据是没有经过任何处理的原始数据.因此,你不能通过XMLSocket连接立即使用XML,你发送和接收的都是纯字符串数据.如果你期望XML,在你处理数据之前,你必须首先将这些数据转换为一个XML的实例.
    下面的这段代码在初始化的时候通过XMLSocket连接到了本地服务器的2900端口.在连接成功之后,一个<test>消息会发送到服务器.onData事件监听者控制从服务器返回的响应.在本例中返回字符串<response><test success='true'/></response>.你可以通过事件的data属性发现为字符串数据,然后XML类的构造函数将字符串转换成为了XML实例.最后,通过使用E4X语法的XML实例的一部分信息.(关于通过使用E4X处理XML的更多详细信息,我们需要另外讨论.)
CODE:


package {
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.DataEvent;
  import flash.net.XMLSocket;
  public class SocketExample extends Sprite {
    private var xmlSocket:XMLSocket;
    public function SocketExample(  ) {
      xmlSocket = new XMLSocket(  );
    
      // Connect listener to send a message to the server
      // after we make a successful connection
      xmlSocket.addEventListener( Event.CONNECT, onConnect );
    
      // Listen for when data is received from the socket server
      xmlSocket.addEventListener( DataEvent.DATA, onData );
      // Connect to the server
      xmlSocket.connect( "localhost", 2900 );
    }
  
    private function onConnect( event:Event ):void {
      xmlSocket.send( "<test/>" );
    }
    private function onData( eventataEvent ):void {
      // The raw string returned from the server.
      // It might look something like this:
      // <response><test success='true'/></response>
      trace( event.data );
    
      // Convert the string into XML    
      var response:XML = new XML( event.data );
    
      // Using E4X, access the success attribute of the "test"
      // element node in the response.
      // Output: true
      trace( response.test.@success );
    }
  }
}
注意:在data事件分发数据之前,XMLSocket实例必须从服务器收到一个表示为空的byte('\\0').也就是说,从服务器仅仅只发送所需要的字符串是不够的,必须在结尾处加入一个表示为空的byte.




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics