`
wgcode
  • 浏览: 593538 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

as3 Socket

 
阅读更多

Socket 套接字连接允许Flash播放器通过指定的端口与服务器通信,socket连接与其他通信技术
最大的不同是socket连接在数据传输完成后不会自动关闭。
当socket连接创建后,连接会一直保持,直到客户端(Flash播放器)和服务端主动关闭,因此
服务器可在任何时间不用客户端请求即可发送数据给客户端。
Socket连接被普遍用于创建多用户应用程序,比如说一个在线聊天室,它有一个服务端程序和
无数个Flash客户端组成。每次客户端发送消息给服务器,服务器检测那些用户可以收到这些消
息并把消息传给指定客户端,这种情况下接收客户端并没有提前请求数据而是通过服务器主动
推送数据的。当客户端关闭时,服务端提示其他客户端某客户端已离线。
Flash播放器提供了两种类型的socket连接。一种是早期版本就有的XMLSocket,Flash播放器9增
加了二进制socket连接。
使用flash.net.XMLSocket类创建XML数据格式的socket连接,使用flash.net.Socket类创建二进制数
据格式socket连接。
XML socket连接以XML数据报交换数据,二进制socket连接是ActionScript 3.0新增的功能,相比
之下更低级,但功能很强大,几乎可以连接任意类型的socket服务端程序。例如二进制sockets 可
连接邮件服务端程序(POP3, SMTP, 和IMAP), 新闻服务器(NNTP), 聊天室服务器或远程桌面
VNC服务器( RFB)。
不管是哪种类型的socket 连接,其通信方式都是异步的,也就是说你不能直接从socket 连接中
读取数据,而是通过事件处理函数进行读取处理。

24.1.
连接Socket
服务器
问题
我想连接socket服务器
解决办法
使用Socket.connect( )或XMLSocket.connect( )方法建立连接并监听connect事件确定连接是否建
立。
讨论
要连接socket服务器,首先要知道域名或IP地址,还要知道端口,不管是使用Socket 还是
XMLSocket,连接步骤是一样的,都是用connect( )方法进行连接,该方法接受两个参数:
host
指定域名或IP地址,如www.example.com或192.168.1.101。
port
数字,指定连接的端口号,必须大于1024,如果小于1024则需服务器提供策略文件允许。
因为是异步通信,connect( )方法不会等待结果而是继续执行下面的语句,因此需要注册事件监
听器来获取连接结果。
注册事件监听器必须在调用connect( )方法之前,当连接成功时connect事件就会触发,下面的例
子演示连接本机2900端口:

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,代码也基本上相同,代码如下:
package {
import flash.display.Sprite;
import flash.events.*;
import flash.net.XMLSocket;
public class SocketExample extends Sprite {
private var socket:XMLSocket;
public function SocketExample( ) {
socket = new XMLSocket( );
// 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 xml socket is now connected..." );
}
}
}

 
如果连接失败,可能的异常有:runtime error,ioError,securityError ,
记住,当用socket连接主机时,要遵循Flash Player安全沙漏规则:
swf 和主机必须在同一个域;
网络上的swf不能连接本地服务器;
本地的swf 不能访问任何网络资源;
要允许域名交叉访问或连接低于1024的端口,需要提供cross-domain 策略文件。

如果Socket 或XMLSocket 对象要使用cross-domain 策略文件, 可通过方法
flash.system.Security.loadPolicyFile( )读取:

Security.loadPolicyFile("http://www.rightactionscript.com/crossdomain.xml");
cross-domain策略文件例子:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domainpolicy.
dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="80,110" />
</cross-domain-policy>

 
24.2.
发送数据
问题
我要发送数据给socket服务器
解决办法
对于Socket对象,是使用write方法(writeByte( ), writeUTFBytes( ), 等等) 把数据写入到缓冲区,
再通过flush( )方法发送数据,对于XMLSocket对象使用send( )方法。
讨论
Socket和XMLSocket类各自定义了不同的APIs来发送数据,首先看一下Socket的API :
当使用Socket对象发送数据时必须先把数据写到缓冲区,Socket类定义了一系列方法用于写数
据,每个方法都是写入不同类型的数据,这些方法是writeBoolean( ), writeByte( ), writeBytes( ),
writeDouble( ), writeFloat( ), writeInt( ), writeMultiByte( ), writeObject( ), writeShort( ), write-
UnsignedInt( ), writeUTF( ), 和writeUTFBytes( ) 。每个方法都接受一种类型的参数, 如
writeBoolean( )接受布尔型参数,writeByte( ), writeDouble( ), writeFloat( ), writeInt( ), writeShort( ),
和writeUnsignedInt( )接受数字参数,writeObject( )方法接受对象参数,writeBytes( )方法允许传递
一个ByteArray类型参数以及偏移量和长度,如下面的写法:
socket.writeBytes(byteArray, 0, byteArray.length);
writeUTF( )和writeUTFBytes( )方法写入字符串,每个方法接受一个字符串参数,writeUTFBytes( )
方法写入字节形式的字符串,writeUTF( )方法写入字节数字。
writeMultiByte( )方法也是写入字符串数据,但可以不使用默认字符集,该方法接受两个参数:
字符串和指定字符集编码,下面的例子写入Unicode编码的字符串:
socket.writeMultiByte("example", "unicode");

利用Socket对象,完全可以用ActionScript写出一个Telnet和POP客户端,这两个协议都是以ASCII
字符为基础的,例如,连接一个POP服务器后,可用下面的代码执行USER命令:
// POP servers expect a newline (\n) to execute the preceding command.
socket.writeUTFBytes("USER exampleUsername\n");
写入的数据实际上还没发送到服务器上,每个方法都死把数据累积到Socket对象上,例如下面的
四个代码并没有把数据发送出去:

socket.writeByte(1);
socket.writeByte(5);
socket.writeByte(4);
socket.writeByte(8);

 
当要发送数据时,必须调用flush( )方法,flush( )方法发送所有的数据并清空缓冲区:
socket.flush( );
XMLSocket类发送数据就比较简单了,发送数据的方法为send( ),send( )方法接受任意类型的数
据类型,它会把参数转换为字符串并发送给服务器,一般这个参数是一个XML对象:
xmlSocket.send(xml);
实际上发送的数据类型是由服务器所决定的,如果服务器接受XML 数据,那必须发送XML 数
据,如果服务器接受URL-编码数据,则必须发送URL-编码数据。
24.3.
接收数据
问题
我想接收socket服务器发送来的数据
解决办法
对于Socket实例可通过ProgressEvent.SOCKET_DATA事件处理函数中读取数据,可用readByte( )
或readInt( )方法
对于XMLSocket实例可通data事件处理函数中读取XML数据
讨论
从socket中接收数据的方法取决于你使用socket类型,Socket和XMLSocket都可以接收数据,但是
两者实现方法有些不同,让我们先看看Socket类是如何做的。
正如前面所讲到的,Flash提供的socket通信方式是异步通信,也就是说仅仅创建socket连接并试图
读取数据这是不可能的,read方法读取数据时并不会等待数据传输过来而立即返回,如果数据还
没准备好而去读取数据会导致异常。

当数据准备好了时,socketData事件就会触发,通过注册该事件处理函数,当数据发送过来时就
会触发,因此可通过该处理函数读取数据。
为了读取服务器发送来的数据,Socket 类提供了一系列read 方法来读取不同类型的数据,例如
通过readByte( )方法读取一个字节,readUnsignedInt( )方法读取一个无符号整数,具体看下面的
表格:
Table
24-1.
Socket
read
methods
for
various
datatypes
还有两个方法没有在上面的表格里,它们是readBytes( )和readUTFBytes( ),readBytes( )方法没有
返回值,它接受三个参数:
bytes
一个flash.util.ByteArray 实例填充读取的数据
offset
一个uint值指定读取数据的偏移量,默认为0
length
一个uint值表示读取的字节数,默认为0,表示所有的数据
readUTFBytes( )方法只接受一个参数,表示读取的UTF-8 字节数,返回一个字符串。
下面的例子代码连接一个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( ) {
方法:返回类型描述字节数
readBoolean():Boolean
读取布尔型数据1
readByte():int
读取一个字节数据1
readDouble():Number
读取IEEE
754
双精度浮点数8
readFloat():Number
读取IEEE
754
单精度浮点数4
readInt():in
读取32
位整数4
readObject():*
读取AMF
格式对象N
readShort():int
读取16
位整数2
readUnsignedByte():uint
读取无符号字节1
readUnsignedInt():uint
读取无符号32
位整数4
readUnsignedShort():uint
读取无符号16
位整数2
readUTF():String
读取UTF-8
字符串n

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( event:ProgressEvent ):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"字符串,则输出:
//Socket接收5字节的数据:
72
101
108
108
111
Socket对象接收的数据都是ASCII编码的文本,我们可以用readUTFBytes( )方法重新构造字符串,
readUTFBytes( )方法需要知道有多少个字节需要转换,用bytesAvailable属性指定字节数:
var string:String = socket.readUTFBytes(socket.bytesAvailable);
XMLSocket类和Socket类基本类似,两者都要注册监听器检测数据是否接收完毕,但是两者读取
数据的方式是不同的。
当数据准备好时XMLSocket 实例发出data 事件,事件类型为flash.events.DataEvent.DATA ,它

其中的data 属性包含接收过来的数据。
从服务器返回的数据都是原始的数据,如果你希望以XML进行处理则需先把数据转换为XML
实例。
下面的代码例子用XMLSocket连接本地服务器,端口为2900,连接成功后,发送<test>消息给服
务器, onData 事件处理函数处理服务器返回的数据, 返回数据为<response><test
success='true'/></response>,注意到该事件的data属性的内容只是字符串数据,需用XML构造器
转换位XML实例,最后通过E4X 语法输出XML:

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( event:DataEvent ):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 );
}
}
}

 
24.4.
与socket
服务器的状态信号交换
问题
我想与服务器进行信号交换以便知道读取的数据内容是什么以及如何进行处理。
解决办法
创建不同的常量来表示协议状态,用这些常量映射与之对应的状态处理函数,在socketData事件
处理函数中通过状态映射表调用对应的状态处理函数。
讨论
连接socket服务器需要经过一个完整的信号交换,通常服务器初始化后发送数据给客户端,客户
端进行回应,服务器再回应,这个完整的处理过程一直重复直到信号交换完成,这个连接才算
建好了。
就像典型的HTTP连接一样,HTTP协议定义了一系列状态代表不同的传输数据,我们现在建立
的socket连接也是最原始的无状态的,同样需要建立各种状态以及维护各种状态的函数功能。
解决办法就是创建不同的状态常量代表服务器发送的不同类型的内容,每个状态关联不同的状
态处理函数。
连接一个socket服务器需要的信号交换可能有:
当客户端连接到服务器时,服务器立即回应,发送一个整数代表服务器所支持的协议版本。
客户端返回一个整数表示可以通信的协议版本。
服务器发送8自己的认证询问。
客户端发送认证给服务器。
如果客户端的回应不合法或协议不一致或不是规定的信息则关闭连接。

要实现这个信号交换过程,首先要创建代表不同状态的常量,例如建立如下常量:
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变量代表当前状态,根据其值调用对应的处理函数:
var processFunc:Function = stateMap[ currentState ];
processFunc( ); // Invoke the appropriate processing function
完整代码如下:

package {
import flash.display.Sprite;
import flash.events.ProgressEvent;
import flash.net.Socket;
import flash.utils.ByteArray;
public class SocketExample extends Sprite {
// The state constants to describe the protocol
public const DETERMINE_VERSION:int = 0;
public const RECEIVE_CHALLENGE:int = 1;
public const NORMAL:int = 2;
// Maps a state to a processing function
private var stateMap:Object;
// Keeps track of the current protocol state
private var currentState:int;
private var socket:Socket;
public function SocketExample( ) {

// Initialzes the states map
stateMap = new Object( );
stateMap[ DETERMINE_VERSION ] = readVersion;
stateMap[ RECEIVE_CHALLENGE ] = readChallenge;
stateMap[ NORMAL ] = readNormalProtocol;
// Initialze the current state
currentState = DETERMINE_VERSION;
// Create and connect the socket
socket = new Socket( );
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
socket.connect( "localhost", 2900 );
}
private function onSocketData( event:ProgressEvent ):void {
// Look up the processing function based on the current state
var processFunc:Function = stateMap[ currentState ];
processFunc( );
}
private function readVersion( ):void {
// Step 1 - read the version from the server
var version:int = socket.readInt( );
// Once the version is read, the next state is receiving
// the challenge from the server
currentState = RECEIVE_CHALLENGE;
// Step 2 - write the version back to the server
socket.writeInt( version );
socket.flush( );
}
private function readChallenge( ):void {
// Step 3 - read the 8 byte challenge into a byte array
var bytes:ByteArray = new ByteArray( );
socket.readBytes( bytes, 0, 8 );

// After the challenge is received, the next state is
// the normal protocol operation
currentState = NORMAL;
// Step 4 - write the bytes back to the server
socket.writeBytes( bytes );
socket.flush( );
}
private function readNormalProtocol( ):void {
// Step 5 - process the normal socket messages here now that
// that handshaking process is complete
}
}
}

 
24.5.
断开与Socket
服务器的连接
问题
我想断开与服务器的连接或通知服务器断开
解决办法
调用Socket.close( ) 或XMLSocket.close( ) 方法关闭连接,或者监听close事件
讨论
当我们连接一个socket连接后,用完时应该关闭连接,释放资源,如果不关闭这会导致占用端口
使其它连接无法建立。
Socket 和XMLSocket关闭socket连接的方法是一样的,都为close( ) 方法:
// Assume socket is a connected Socket instance
socket.close( ); // Disconnect from the server
调用XMLSocket实例的方法:
// Assume xmlSocket is a connected XMLSocket instance
xmlSocket.close( ); // Disconnect from the server

close( ) 方法通知服务器客户端已经断开连接,如果服务器先关闭呢,那客户端该怎么知道呢,
可通过监听客户端的close事件,注册事件类型为Event.CLOSE:
var socket:Socket = new Socket( );
socket.addEventListener( Event.CLOSE, onClose );
24.6.
处理Socket
异常
问题
使用socket如何处理可能引发的异常
解决办法
使用try/catch 处理I/O 和(EOF) 异常
讨论
Socket 和XMLSocket 类处理异常的方式基本类似,当调用connect( )方法时,如遇到下面的情况
Socket 和XMLSocket 对象都抛出SecurityError:
.swf 被认为本地非安全
端口号高于655535.
当调用send( ) (XMLSocket) 或flush( ) (Socket),如果没有事先连接好,则抛出IOError,可先通
过socket对象的connected属性是否为true,再调用send( ) 或flush( )。如下面的代码:

if ( socket.connected ) {
try {
socket.flush( );
}
catch( error:IOError ) {
logInstance.write( "socket.flush error\n" + error );
}
}
else {
connectToSocketServer( ); //进行socket连接
}

 
Socket 所有的read 方法都可能抛出EOFError和IOError,但没有数据可读而读取时引发EOF异
常,当socket已关闭而去读取时引发I/O 异常。

 

分享到:
评论

相关推荐

    FLASH AS3 SOCKET收发16进制示例

    在AS3中,我们可以使用Socket类来实现这一功能。本示例主要探讨如何在Flash AS3中使用Socket类来发送和接收16进制数据。 首先,让我们理解16进制。16进制(Hexadecimal)是一种逢16进1的进位制,主要用于表示计算机...

    flash as3 socket编程基础

    ### Flash AS3 Socket编程基础知识详解 #### 一、引言 在现代互联网应用开发中,实时通信技术变得越来越重要。而Socket编程作为一种实现客户端与服务器之间实时数据交换的有效手段,在Flash开发领域同样占据着重要...

    AS3 Socket 基础知识(很全面) 1

    AS3 Socket基础知识是网络通信的重要组成部分,特别是在网络时代,它被广泛应用于各种应用程序中,因为“一切皆Socket”。网络进程间的通信需要一个唯一标识,TCP/IP协议族通过IP地址识别网络主机,结合传输层的...

    as3socket通信

    as3socket向服务器传输数据和接收服务器的数据,自己,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...

    java和as3 socket通信 解决安全沙箱问题

    Java和ActionScript 3 (AS3) 的Socket通信在实现跨平台交互时是常见的技术手段,尤其是在处理实时数据传输和游戏开发中。然而,由于AS3运行在Flash Player的沙箱环境中,它受到一系列安全限制,包括不能直接与非同一...

    as3socket写的rtmp协议类

    as3socket写的rtmp协议类,完成基本的连接功能,可以获取服务器返回的16进制数据

    as3_socket

    ### AS3 Socket编程详解 #### 一、引言 在当今互联网时代,实时通信变得尤为重要。ActionScript 3.0(AS3)作为Flash平台的主要编程语言之一,提供了强大的网络功能,包括Socket编程的支持。本文将详细介绍AS3中的...

    as3_Socket_的简单实例

    AS3中的`Socket`类是Flash Player 9引入的新特性,用于创建基于TCP/IP协议的网络连接。Socket连接允许应用程序直接与远程服务器进行低级别的数据通信,而不依赖于特定的应用层协议,如HTTP或HTTPS。这种直接的连接...

    AS3 SOCKET

    AS3中的SOCKET技术是ActionScript 3.0中用于实现网络通信的一种方式,它允许客户端(通常是Flash应用程序)与服务器之间进行低级的、基于TCP/IP协议的双向数据传输。在AS3中,有两种主要的类用于实现SOCKET通信:...

    AS3使用Socket的简单例子.txt

    ### AS3使用Socket的简单例子 #### 知识点概览 - **AS3 Socket编程基础** - **创建与配置XMLSocket对象** - **事件监听器的设置与使用** - **连接服务器及发送数据** - **接收服务器响应** #### 知识点详细解析 #...

    (AS3)socket+客户端与服务端+实例

    本文将深入探讨基于ActionScript 3(AS3)的Socket通信,包括客户端与服务端的交互,以及如何通过提供的实例来理解这一过程。我们将不涉及具体代码,而是详细解释相关的概念和技术要点。 首先,Socket是网络编程中...

    一段as3.0与c++socket通信的例子(as端代码)

    在本示例中,我们关注的是AS3.0如何与C++实现的服务器进行Socket通信。 Socket通信是一种基于TCP/IP协议的通信方式,允许两台计算机之间建立直接的数据传输通道。在AS3.0中,我们可以使用`flash.net.Socket`类来...

    flash actionscript3游戏开发之as3的socket通信方式介绍即使用XMLSocket.zip

    本文将深入探讨AS3中的Socket通信方式,特别是利用XMLSocket进行网络交互的细节。 首先,XMLSocket是AS3中用于低级网络通信的类,它提供了双向、全双工的数据流,适合于游戏开发中的实时数据交换,如玩家状态同步、...

    php与flash as3 socket通信传送文件实现代码

    前段时间在flashseer看到有人提到:可以通过socket方式传送swf文件,让用户无法获取到swf文件… 当时还没有出as3的反编译,所以对程序的保护没有在意.随着反编译程序的平民化,不希望别人看到源代码的朋友就比较着急… ...

    flash as3.0 socket编程

    3. 从 Socket 服务器读数据 我们可以使用 read() 方法来从 Socket 服务器读取数据。read() 方法可以从服务器读取数据,并将其存储在 ByteArray 对象中。 4. 同 Socket 服务器进行握手 在与 Socket 服务器建立连接...

    as3带进度条上传实例

    ### AS3 带进度条上传实例解析 在Adobe Flex框架下使用ActionScript 3 (AS3) 进行文件上传开发时,加入进度条功能是提升用户体验的关键环节。本篇将详细介绍如何实现一个带有进度条的文件上传功能,包括连接服务器...

    flashas3.0socket编程

    资源名称:flash as3.0 socket编程 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。

    ActionScript 3.0 Socket 源码

    根据给定文件中的标题、描述、标签以及部分内容,本文将详细介绍有关ActionScript 3.0 (AS3) 中Socket编程的基础知识与应用实践。 ### 一、ActionScript 3.0 Socket简介 #### 1. Socket概念 在ActionScript 3.0中...

    Flex 利用socket断点续传

    3. 可能还包含配置文件,如XML或properties文件,用于设置Socket连接参数、服务器地址等。 为了确保程序的稳定性和性能,开发者需要考虑以下几个方面: - 错误处理:对可能出现的网络异常、线程错误等进行妥善处理...

Global site tag (gtag.js) - Google Analytics