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