[轉(zhuǎn)] ActionScript3.0 Socket
介紹:Socket 連接允許Flash Player通過特定的網(wǎng)絡(luò)端口來發(fā)送和加載數(shù)據(jù)。Socket和server連接的最大的不同點是Socket連接在數(shù)據(jù)傳輸完畢之后是不會自動的關(guān)閉。
在一個socket連接建立之后,這個連接就會一直處于打開狀態(tài),除非客戶端或者服務(wù)器段顯式的關(guān)閉它。基于此,socket允許一種特殊的數(shù)據(jù)傳輸方式,叫做data push,這種凡是允許客戶段的Flash Player沒有發(fā)送請求的時候,服務(wù)器可以在任何時候把數(shù)據(jù)傳送到客戶端播放器。
Socket連接典型的應(yīng)用就是創(chuàng)建多用戶的應(yīng)用程序,一中此類應(yīng)用程序比如在線聊天室。聊天室由一個中心服務(wù)器和一些連接到服務(wù)器的Flash Player客戶端組成。每次客戶端的.swf文件發(fā)送一條消息到服務(wù)器,服務(wù)器判斷那個客戶端應(yīng)該接受這個消息,然后就把這條消息從打開的連接上發(fā)送給合適的用戶。這種情況下,接受消息的客戶并沒有請求接受一個消息,但是這個消息從服務(wù)器端發(fā)送出去了。當(dāng)一個客戶關(guān)閉連接的時候,服務(wù)器通知所有的客戶有人離開的聊天系統(tǒng)。
Flash Player可以發(fā)送兩種socket連接到socket服務(wù)器,兩種方式有相同的行為和操作,但是也有細小的不同。第一種是XML socket連接,這種方式和之前的Player版本中的XMLSocket類似,對Flash 9來說binary socket是全新的方式。
我們通過flash.net.XMLSocket和flash.net.Socket兩個類來建立socket連接。
XML socket 以文本為傳輸方式,客戶端和服務(wù)器通過包含數(shù)據(jù)的XML包來交換數(shù)據(jù),通過分析XML包的內(nèi)容來執(zhí)行動作。
Binary socket是ActionScript3.0的新東西,這種方式允許我們通過原始鏈接來傳遞二進制信息。Binary socket比XML socket要更加的高效,因為binary socket需要了低級的類型信息,這種方式更加強大,因為我們可以連接到更加寬廣的socket服務(wù)器上。比如,binary socket允許我們連接到郵件服務(wù)器(POP3,SMTP,IMAP),新聞服務(wù)器(通過NNTP),聊天服務(wù)器,甚至是桌面共享和遠程桌面通過連接VNC服務(wù)器。
不管什么樣的socket連接類型,他們都是異步執(zhí)行的,這就意味著我們不能通過socket鏈接來獲得數(shù)據(jù)知道我們被通知數(shù)據(jù)加載結(jié)束,所有的數(shù)據(jù)加載都必須通過事件處理來自動執(zhí)行。當(dāng)我們需要在程序運行的時候通過加載一些數(shù)據(jù)來使它繼續(xù)運行下去的時候就需要同步的數(shù)據(jù)加載,這種方式比較容易編寫程序,但是不夠高效。通過這章的學(xué)習(xí)你會更多學(xué)到如何通過異步的方式來加載數(shù)據(jù)。
連接到一個Socket Server
問題:我們想建立一個到socket服務(wù)器的連接
解決:Sokect.connect()或者XMLSocket.connect()方法。
討論:在我們連接到一個服務(wù)器之前,有兩個重要的信息我們必須知道,第一個是服務(wù)器的域名或者ip地址,第二個是我們連接的端口。
不論我們用的是那種連接方式,連接的處理過程完全一樣,兩個連接類都有一個connect方法,這個方法接受兩個參數(shù):
Port:一個整形類型的參數(shù)指定了我們連接到的服務(wù)器的端口號碼。端口號碼最小必須是1024,除非有配置文件說明端口號碼可以小于1024。
由于在Flash中socket編程是異步這樣的事實,因此connect方法是不會等到socket調(diào)用返回就會執(zhí)行connect語句的下面一條語句的,如果你想在連接完全建立之前做一些和socket的交互工作,你的代碼就會遇到一些錯誤。
比較正確的做法就是在我們調(diào)用connect方法之前,我們添加一些偵聽事件到sokect對象,當(dāng)連接成功建立的時候,會分發(fā)一個connect事件,這個事件告訴我們連接已經(jīng)建立好了,我們可以開始和socket交互了。
如果我們想鏈接到本地的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來建立連接,基本的代碼完全一樣我們只需要用XMLSocket來代替Socket類。
如果連接失敗,會產(chǎn)生運行時錯誤,或者拋出ioError或者securityErrot異常,來通知連接沒有完全成功的建立。更多的關(guān)于異常事件參考錯誤處理章節(jié)
記住,在我們連接到一個服務(wù)器的時候,下邊的Flash Player sandbox要遵守:
1. swf文件必須和主機在相同的域當(dāng)中
2. 跨域的swf文件是不能訪問本地服務(wù)器的
3. 本地非信任的swf文件不能訪問任何的網(wǎng)絡(luò)資源
4. 如果允許跨域并且端口號低于1024的訪問時,必須配置跨域配置文件
任何違反安全砂箱的操作比如連接到不信任域或者很小的端口的操作都會引發(fā)securityError事件,這些問題可以通過編寫配置文件來解決。為了在Socket和XMLSocket中使用跨域的配置文件,我們必須加載配置文件:
Security.loadPolicyFile("http://www.rightactionscript.com/crossdomain.xml");
在我們編輯配置文件時,我們不應(yīng)該僅僅指定受信任的域,還應(yīng)該有受信任的端口,如果你沒有指定任何的端口,F(xiàn)lash Player將默認80是唯一受信任的端口,你可以通過在port屬性的值后邊添加一個逗號來制定其它的受信任的端口號碼,如下:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="80,110" />
</cross-domain-policy>
發(fā)送數(shù)據(jù)
問題:我們想把數(shù)據(jù)傳送到socket服務(wù)器
解決:對Socket對象來說,使用write方法(wirteByte(),writeUTFBytes()),來把數(shù)據(jù)寫入緩沖區(qū),然后調(diào)用flush()方法把數(shù)據(jù)刷新到輸出流。對XMLSocket對象,使用send方法。
討論:Socket和XMLSocket定義不同的api來發(fā)送數(shù)據(jù)到服務(wù)器,讓我們先來了解下API.
當(dāng)我們向使用Socket對象來發(fā)送數(shù)據(jù)的時候,首先必須把數(shù)據(jù)寫到緩沖區(qū),Socket類定義了一些用來寫數(shù)據(jù)的方法.每個方法都用來寫不同類型的數(shù)據(jù).這些方法有: writeBoolean( ), writeByte( ), writeBytes( ), writeDouble( ), writeFloat( ), writeInt( ), writeMultiByte( ), writeObject( ), writeShort( ), write- UnsignedInt( ), writeUTF( ), and writeUTFBytes( ).大部分這些方法接受的參數(shù)通過方法的名字已經(jīng)暗示了.
在我們使用的時候到底使用那個方法完全取決于我們希望發(fā)送什么樣的數(shù)據(jù)到服務(wù)器,使用Socket類的時候,你可以完全通過ActionScript來把數(shù)據(jù)寫到Telent或者POP mail服務(wù)器.兩種協(xié)議都期望ASCII文本命令,比如,在我們連接到一個POP服務(wù)器之后,我們就可以通過USER命令來指定一個用戶,下邊的例子就是向Socket服務(wù)器寫這樣一個命令的例子:
// POP servers expect a newline (\n) to execute the preceding command.
socket.writeUTFBytes("USER exampleUsername\n");
把數(shù)據(jù)寫入Socket對象并不意味著就已經(jīng)傳給服務(wù)器了,調(diào)用每個write方法都會把數(shù)據(jù)添加到Socket對象上,比如,下邊的例子中我們把四個字節(jié)的數(shù)據(jù)添加到Socket對象,但是他們中的任何一個都沒有被發(fā)送到服務(wù)器:
socket.writeByte(1);
socket.writeByte(5);
socket.writeByte(4);
socket.writeByte(8);
當(dāng)我們向把Socket中的數(shù)據(jù)傳送到服務(wù)器的時候,調(diào)用Socket對象的flush()
方法.
XMLSocket對象基本上和Socket對象有同樣的Api接口,通過調(diào)用send()方法來把數(shù)據(jù)傳送到服務(wù)器.send方法接受任何類型的參數(shù),它會把這個參數(shù)轉(zhuǎn)換成string類型,然后傳送到服務(wù)器.一般情況下這個參數(shù)是XML對象或者一個字符串里邊包含結(jié)構(gòu)化的XML數(shù)據(jù):
xmlSocket.send(xml);
然而,精確的數(shù)據(jù)格式完全依賴于服務(wù)器段的期望格式,如果服務(wù)器期望格式化的XML數(shù)據(jù),那么你就必須傳遞格式化的XML數(shù)據(jù)過去,如果服務(wù)器期望URL編碼的數(shù)據(jù),那么你就必須傳遞這樣的數(shù)據(jù)過去.
接受數(shù)據(jù)
To be continuing……
[源] http://tb.blog.csdn.net/TrackBack.aspx?PostId=1688278