通訊端Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本 通訊端是兩個電腦程序之間所建立的網路連線類型。一般而言,這些程序是在兩部不同的電腦上執行,而這兩部電腦連接至相同的網際網路通訊協定 (IP) 網路。不過,使用特殊「本機主機」IP 位址,連接的程序就可以在相同的電腦上執行。 Adobe Flash Player 支援用戶端「傳輸控制通訊協定 (TCP)」通訊端。Flash Player 應用程式可以連接至另一個做為通訊端伺服器的程序,但是無法接受來自其他程序的傳入連線要求。換句話說,Flash Player 應用程式可以連接至 TCP 伺服器,但是無法做為伺服器。 Flash Player API 也包括 XMLSocket 類別。XMLSocket 類別使用 Flash Player 特定通訊協定,讓您可以與瞭解該通訊協定的伺服器交換 XML 訊息。XMLSocket 類別在 ActionScript 1 時引進,目前仍提供舊版相容性支援。一般而言,除非您連接至為了與 Flash XMLSockets 通訊而特別建立的伺服器,否則新的應用程式應該使用 Socket 類別。 Adobe AIR 新增多種其他類別,以進行通訊端型網路程式設計。AIR 應用程式可以使用 ServerSocket 類別做為 TCP 通訊端伺服器,而且可以使用 SecureSocket 類別連接至需要 SSL 或 TLS 安全性的通訊端伺服器。AIR 應用程式也可以使用 DatagramSocket 類別傳送和接收「通用資料包通訊協定 (UDP)」訊息。 TCP 通訊端「傳輸控制通訊協定」(TCP) 提供一種方法,可透過持續的網路連線交換訊息。TCP 保證可讓傳送的所有訊息以正確的順序送達 (重大網路問題除外)。TCP 連線需要一個「用戶端」和一個「伺服器」。Flash Player 可以建立用戶端通訊端。Adobe AIR 可以額外建立伺服器通訊端。 下列 ActionScript API 可提供 TCP 連線:
二進位用戶端通訊端二進位通訊端連線與 XML 通訊端連線相當類似,只是用戶端與伺服器並不限於交換 XML 訊息;但這種連線方式會改以二進位資訊來傳輸資料。因此,您可以連線至範圍更廣的服務,包括郵件伺服器 (POP3、SMTP 和 IMAP) 和新聞伺服器 (NNTP)。 Socket 類別Socket 類別可讓您進行通訊端連線,以及讀取和寫入原始二進位資料。Socket 類別適用於與使用二進位通訊協定的伺服器交互作業。您可以利用二進位通訊端連線,透過撰寫程式碼,讓不同的網際網路通訊協定 (例如 POP3、SMTP、IMAP 和 NNTP) 之間可以彼此進行互動。然後,這種互動可以讓您的應用程式連線至郵件和新聞伺服器。 Flash Player 可以使用伺服器的二進位通訊協定,直接搭配伺服器運作。有些伺服器會使用 big-endian 位元組順序,有些伺服器會使用 little-endian 位元組順序。由於「網路位元組順序」為 big-endian,所以網際網路上的多數伺服器都是使用 big-endian 位元組順序。由於 Intel® x86 架構使用的是 little-endian 位元組順序,所以這種順序也廣為使用。對於所要使用的 Endian 位元組順序,應符合傳送或接收資料之伺服器的位元組順序。根據預設,由 IDataInput 和 IDataOutput 介面執行的所有作業,以及實作這些介面的類別 (ByteArray、Socket 和 URLStream) 都是以 big-endian 格式編碼,也就是最高位元組在前;選擇這個預設位元組順序,以符合 Java 和正式網路位元組順序。若要變更所使用的 big-endian 或 little-endian 位元組順序,請將 endian 屬性設為 Endian.BIG_ENDIAN 或 Endian.LITTLE_ENDIAN。 Socket 類別會繼承 IDataInput 和 IDataOutput 介面 (位在 flash.utils 套件中) 定義的所有方法 。您必須使用這些方法,將資料寫入 Socket 或者從中讀取資料。 如需詳細資訊,請參閱: 安全用戶端通訊端 (AIR)您可以使用 SecureSocket 類別來連接至使用「安全通訊端階層版本 4」(SSLv4) 或「傳輸層安全性 (Transport Layer Security,TLS) 版本 1」(TLSv1) 的通訊端伺服器。安全通訊端提供三個優點:伺服器驗證、資料完整性以及訊息機密性。執行階段會使用伺服器憑證及其與使用者信任儲存區中根或間接憑證授權單位的關係,來驗證伺服器。執行階段需要 SSL 和 TLS 通訊協定實作所使用的密碼演算法,才能提供資料完整性和訊息機密性。 當您使用 SecureSocket 物件連線至伺服器時,執行階段會使用憑證信任儲存區檢查伺服器憑證的有效性。在 Windows 和 Mac 上,作業系統會提供信任儲存區。在 Linux 上, 執行階段提供它自己的信任儲存區。 如果伺服器憑證無效或者不被信任,執行階段會傳送 ioError 事件。您可以檢查 SecureSocket 物件的 serverCertificateStatus 屬性,判斷驗證失敗原因。與不具有效和信任憑證的伺服器通訊時,不會提供任何資料。 CertificateStatus 類別會定義代表可能驗證結果的字串常數:
與 SecureSocket 物件通訊時,伺服器一定要使用安全的通訊協定,而且具有一個有效、受信任的憑證。其他方面,使用 SecureSocket 物件與使用 Socket 物件並無不同。 並不是所有平台都支援 SecureSocket 物件。 請使用 SecureSocket 類別的 isSupported 屬性,來測試執行階段是否支援在目前的用戶端電腦上使用 SecureSocket 物件。 如需詳細資訊,請參閱: TCP 通訊端範例:建立 Telnet 用戶端Telnet 範例將示範使用 Socket 類別與遠端伺服器建立連線並傳輸資料的技巧。這個範例將示範下列技巧:
若要取得此樣本的應用程式檔案,請參閱 www.adobe.com/go/learn_programmingAS3samples_flash_tw。您可以在 Samples/Telnet 檔案夾中找到 Telnet 應用程式檔案,此應用程式是由下列檔案組成:
Telnet 通訊端應用程式概觀主 TelnetSocket.mxml 檔案負責建立整個應用程式的使用者介面 (UI)。 除了負責建立 UI 之外,這個檔案還會定義兩個方法 (login() 和 sendCommand()),用來讓使用者連線至指定的伺服器。 下列程式碼將列出主應用程式檔案中的 ActionScript: import com.example.programmingas3.socket.Telnet; private var telnetClient:Telnet; private function connect():void { telnetClient = new Telnet(serverName.text, int(portNumber.text), output); console.title = "Connecting to " + serverName.text + ":" + portNumber.text; console.enabled = true; } private function sendCommand():void { var ba:ByteArray = new ByteArray(); ba.writeMultiByte(command.text + "\n", "UTF-8"); telnetClient.writeBytesToSocket(ba); command.text = ""; } 程式碼的第一行會從自訂的 com.example.programmingas.socket 套件中匯入 Telnet 類別。程式碼的第二行會宣告 Telnet 類別的實體 telnetClient,這個實體稍後將由 connect() 方法進行初始化作業。接著,宣告 connect() 方法並對之前宣告的 telnetClient 變數進行初始化作業。這個方法會將使用者指定的 telnet 伺服器名稱、telnet 伺服器連接埠和參考傳遞給顯示清單上的 TextArea 組件,以顯示來自通訊端伺服器的文字回應。connect() 方法的最後兩行則是設定「面板」的 title 屬性並啟用「面板」組件,讓使用者可以將資料傳送至遠端伺服器。主應用程式檔案中的最後一個方法 sendCommand(),會用來將使用者的命令傳送到遠端伺服器做為 ByteArray 物件。 Telnet 類別概觀Telnet 類別負責連線至遠端 Telnet 伺服器以及傳送/接收資料。 Telnet 類別會宣告下列私有變數: private var serverURL:String; private var portNumber:int; private var socket:Socket; private var ta:TextArea; private var state:int = 0; 第一個變數 serverURL 包含使用者指定要連線的伺服器位址。 第二個變數 portNumber 是目前正在執行 Telnet 伺服器的埠號。根據預設,Telnet 服務是在埠號 23 上執行。 第三個變數 socket 是 Socket 實體,它的工作是嘗試連線至由 serverURL 和 portNumber 變數定義的伺服器。 第四個變數 ta 是「舞台」上 TextArea 組件實體的參考。這個組件會用來顯示來自遠端 Telnet 伺服器的回應,或任何可能的錯誤訊息。 最後一個變數 state 是一項數值,用來決定您 Telnet 用戶端可支援的選項。 如前所述,Telnet 類別的建構函式是由主應用程式檔案中的 connect() 方法來呼叫。 Telnet 建構函式會使用三個參數:server、port 和 output。server 和 port 參數可以指定執行 Telnet 服務之伺服器的伺服器名稱和埠號。最後一個參數 output 是「舞台」上 TextArea 組件實體的參考,會用來將伺服器輸出顯示給使用者。 public function Telnet(server:String, port:int, output:TextArea) { serverURL = server; portNumber = port; ta = output; socket = new Socket(); socket.addEventListener(Event.CONNECT, connectHandler); socket.addEventListener(Event.CLOSE, closeHandler); socket.addEventListener(ErrorEvent.ERROR, errorHandler); socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); socket.addEventListener(ProgressEvent.SOCKET_DATA, dataHandler); Security.loadPolicyFile("http://" + serverURL + "/crossdomain.xml"); try { msg("Trying to connect to " + serverURL + ":" + portNumber + "\n"); socket.connect(serverURL, portNumber); } catch (error:Error) { msg(error.message + "\n"); socket.close(); } } 將資料寫入通訊端若要將資料寫入通訊端連線,您可以呼叫 Socket 類別中的任何寫入方法。這些寫入方法包括 writeBoolean()、writeByte()、writeBytes()、writeDouble() 以及其他等等。然後,使用 flush() 方法,清除輸出緩衝區的資料。在 Telnet 伺服器中,會使用 writeBytes() 方法將資料寫入通訊端連線,此方法會以位元組陣列做為參數,並將它傳送至輸出緩衝區。writeBytesToSocket() 方法如下所示: public function writeBytesToSocket(ba:ByteArray):void { socket.writeBytes(ba); socket.flush(); } 主應用程式檔案中的 sendCommand() 方法會呼叫此方法。 顯示來自通訊端伺服器的訊息每當從通訊端伺服器收到訊息或發生事件時,就會呼叫自訂的 msg() 方法。這個方法會將字串附加至「舞台」上的 TextArea,然後呼叫自訂的 setScroll() 方法,讓 TextArea 組件捲動到底部。下列範例將示範如何使用 msg() 方法: private function msg(value:String):void { ta.text += value; setScroll(); } 如果沒有設定自動捲動 TextArea 組件的內容,使用者就必須以手動方式將捲軸拖曳到文字區域,才能看到最新的伺服器回應。 捲動 TextArea 組件setScroll() 方法中只包含一行 ActionScript,可以垂直捲動 TextArea 組件的內容,以便讓使用者看到最後傳回的文字。下列程式碼片段將說明如何使用 setScroll() 方法: public function setScroll():void { ta.verticalScrollPosition = ta.maxVerticalScrollPosition; } 這個方法會設定 verticalScrollPosition 屬性,也就是目前顯示的最上面一列字元的行號,並將它設為 maxVerticalScrollPosition 屬性的值。 XML 通訊端XML 通訊端可讓您與遠端伺服器建立連線,該連線會保持開啟,直到明確關閉後才會中斷。您可以在伺服器和用戶端之間交換字串資料,例如 XML。使用 XML 通訊端伺服器的好處是,用戶端不需要明確地要求資料。伺服器可以不需等待要求直接傳送資料,並可將資料傳送給每個連線的用戶端。 在 Flash Player 和應用程式安全執行程序外的 Adobe AIR 內容中,目標伺服器上必須有通訊端原則檔才能進行 XML 通訊端連線。如需詳細資訊,請參閱網站控制 (原則檔)、連線至通訊端。 XMLSocket 類別無法自動通過防火牆,因為它跟 RTMP 通訊協定 (Real-Time Messaging Protocol) 不一樣,XMLSocket 並不具有 HTTP 穿透技術功能。如果您需要使用 HTTP 穿透技術,請考慮改用 Flash Remoting 或 Flash Media Server (可支援 RTMP)。 下列限制適用於 Flash Player 內容或應用程式安全執行程序之外的 AIR 應用程式內容,可以使用 XMLSocket 物件連線至伺服器的方式和位置:
備註: 設定伺服器與 XMLSocket 物件通訊可能會很困難。如果應用程式不需要即時的互動性,請使用 URLLoader 類別取代 XMLSocket 類別。
您可以使用 XMLSocket 類別的 XMLSocket.connect() 和 XMLSocket.send() 方法,透過通訊端連線在伺服器之間來回傳輸 XML。XMLSocket.connect() 方法會與網站伺服器的連接埠建立通訊端連線。XMLSocket.send() 方法會將 XML 物件傳遞到通訊端連線中所指定的伺服器。 當您叫用 XMLSocket.connect() 方法時,應用程式會開啟與伺服器之間的 TCP/IP 連線,並將該連線保持在開啟狀態,直到發生下列其中一個事件:
以 XMLSocket 類別連接到伺服器若要建立通訊端連線,必須建立伺服器端應用程式來等待通訊端連線要求,並將回應傳送到 Flash Player 或 AIR 應用程式中。這類型的伺服器端應用程式可以使用 AIR 或像是 Java、Python 或 Perl 這類程式語言來編寫。若要使用 XMLSocket 類別,伺服器電腦必須執行一個常駐程式,才能了解 XMLSocket 類別所使用的簡單通訊協定。
建立並連線至 Java XML 通訊端伺服器下列程式碼將示範如何以 Java 撰寫一個簡單的 XMLSocket 伺服器,它會接受傳入的連線,並在命令提示視窗中顯示收到的訊息。雖然您可以在透過命令列啟動伺服器時,指定不同的埠號,但根據預設,新的伺服器會建立在本機電腦的連接埠 8080 上。 建立新的文字文件,並在其中加入下列程式碼: import java.io.*; import java.net.*; class SimpleServer { private static SimpleServer server; ServerSocket socket; Socket incoming; BufferedReader readerIn; PrintStream printOut; public static void main(String[] args) { int port = 8080; try { port = Integer.parseInt(args[0]); } catch (ArrayIndexOutOfBoundsException e) { // Catch exception and keep going. } server = new SimpleServer(port); } private SimpleServer(int port) { System.out.println(">> Starting SimpleServer"); try { socket = new ServerSocket(port); incoming = socket.accept(); readerIn = new BufferedReader(new InputStreamReader(incoming.getInputStream())); printOut = new PrintStream(incoming.getOutputStream()); printOut.println("Enter EXIT to exit.\r"); out("Enter EXIT to exit.\r"); boolean done = false; while (!done) { String str = readerIn.readLine(); if (str == null) { done = true; } else { out("Echo: " + str + "\r"); if(str.trim().equals("EXIT")) { done = true; } } incoming.close(); } } catch (Exception e) { System.out.println(e); } } private void out(String str) { printOut.println(str); System.out.println(str); } } 將文件儲存到硬碟並命名為 SimpleServer.java,然後使用 Java 編譯器加以編譯,以建立名為 SimpleServer.class 的 Java 類別檔案。 開啟命令列提示,並輸入 java SimpleServer,就可以啟動 XMLSocket 伺服器。SimpleServer.class 檔案可以位於本機電腦或網路上的任何位置,不一定要放在網站伺服器的根目錄下。 如果因為檔案不在 Java 類別路徑內而無法啟動伺服器,請嘗試使用 java -classpath .SimpleServer 來啟動伺服器。 若要從 應用程式連線至 XMLSocket,必須先建立 XMLSocket 類別的新實體,然後在傳遞主機名稱和埠號期間呼叫 XMLSocket.connect() 方法,如下所示: var xmlsock:XMLSocket = new XMLSocket(); xmlsock.connect("127.0.0.1", 8080); 每當您從伺服器接收資料,就會傳送 data 事件 (flash.events.DataEvent.DATA): xmlsock.addEventListener(DataEvent.DATA, onData); private function onData(event:DataEvent):void { trace("[" + event.type + "] " + event.data); } 若要將資料傳送至 XMLSocket 伺服器,請使用 XMLSocket.send() 方法並傳遞 XML 物件或字串。Flash Player 會將所提供的參數轉換成 String 物件,並在內容後面加上零 (0) 位元組後傳送到 XMLSocket 伺服器: xmlsock.send(xmlFormattedData); XMLSocket.send() 方法並不會傳回值來指出資料是否已傳輸成功。如果在傳送資料時發生錯誤,就會擲出 IOError 錯誤。 傳送到 XML 通訊端伺服器的每項訊息都必須以換行 (\n) 字元做為結尾。 如需詳細資訊,請參閱 XMLSocket。 伺服器通訊端使用 ServerSocket 類別,允許其他程序使用「傳輸控制通訊協定」(TCP) 通訊端連線至您的應用程式。連線程序可以在本機電腦或其他連接網路的電腦上執行。當 ServerSocket 物件收到連線要求時,就會傳送 connect 事件。 ServerSocketConnectEvent 物件在傳送時,會加上內含 Socket 物件的事件。以後與其他程序通訊時,就可以使用這個 Socket 物件。 偵聽傳入的通訊端連線:
ServerSocket 物件持續偵聽新的連線,直到您呼叫 close() 方法。 以下程式碼範例會說明如何建立通訊端伺服器應用程式。範例會偵聽連接埠 8087 的傳入連線。 收到連線之後,該範例會傳送訊息 ("已連線" 字串) 至用戶端通訊端。然後,伺服器會將任何收到的訊息回傳給用戶端。 package { import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.ServerSocketConnectEvent; import flash.net.ServerSocket; import flash.net.Socket; public class ServerSocketExample extends Sprite { private var serverSocket:ServerSocket; private var clientSockets:Array = new Array(); public function ServerSocketExample() { try { // Create the server socket serverSocket = new ServerSocket(); // Add the event listener serverSocket.addEventListener( Event.CONNECT, connectHandler ); serverSocket.addEventListener( Event.CLOSE, onClose ); // Bind to local port 8087 serverSocket.bind( 8087, "127.0.0.1" ); // Listen for connections serverSocket.listen(); trace( "Listening on " + serverSocket.localPort ); } catch(e:SecurityError) { trace(e); } } public function connectHandler(event:ServerSocketConnectEvent):void { //The socket is provided by the event object var socket:Socket = event.socket as Socket; clientSockets.push( socket ); socket.addEventListener( ProgressEvent.SOCKET_DATA, socketDataHandler); socket.addEventListener( Event.CLOSE, onClientClose ); socket.addEventListener( IOErrorEvent.IO_ERROR, onIOError ); //Send a connect message socket.writeUTFBytes("Connected."); socket.flush(); trace( "Sending connect message" ); } public function socketDataHandler(event:ProgressEvent):void { var socket:Socket = event.target as Socket //Read the message from the socket var message:String = socket.readUTFBytes( socket.bytesAvailable ); trace( "Received: " + message); // Echo the received message back to the sender message = "Echo -- " + message; socket.writeUTFBytes( message ); socket.flush(); trace( "Sending: " + message ); } private function onClientClose( event:Event ):void { trace( "Connection to client closed." ); //Should also remove from clientSockets array... } private function onIOError( errorEvent:IOErrorEvent ):void { trace( "IOError: " + errorEvent.text ); } private function onClose( event:Event ):void { trace( "Server socket closed by OS." ); } }} 如需詳細資訊,請參閱: UDP 通訊端 (AIR)「通用資料包通訊協定」(UDP) 提供一種方法,可透過無狀態網路連線來交換訊息。UDP 不保證會按照順序傳送訊息,或者訊息是否真的已傳送。利用 UDP,作業系統的網路程式碼通常會花較少的時間進行封送、追蹤以及確認訊息。因此,UDP 訊息送達目的地應用程式的時間,通常會比 TCP 訊息的延遲較短。 當您必須傳送即時資訊,例如遊戲中的位置更新,或者語音聊天應用程式的聲音封包時,UDP 通訊端通訊十分有用。在這些應用程式中,部分資料遺失是可接受的,而且低的傳輸延遲比保證送到更為重要。至於絕大部分的其他用途方面,TCP 通訊端是較佳的選擇。 您的 AIR 應用程式可以使用 DatagramSocket 與 DatagramSocketDataEvent 類別來傳送和接收 UDP 訊息。傳送或接收 UDP 訊息:
以下程式碼範例會說明應用程式如何收發 UDP 訊息。這個範例會將內含「Hello」這個字串的單一訊息傳送到目標電腦。它也會追蹤任何接收到的訊息內容。 package { import flash.display.Sprite; import flash.events.DatagramSocketDataEvent; import flash.events.Event; import flash.net.DatagramSocket; import flash.utils.ByteArray; public class DatagramSocketExample extends Sprite { private var datagramSocket:DatagramSocket; //The IP and port for this computer private var localIP:String = "192.168.0.1"; private var localPort:int = 55555; //The IP and port for the target computer private var targetIP:String = "192.168.0.2"; private var targetPort:int = 55555; public function DatagramSocketExample() { //Create the socket datagramSocket = new DatagramSocket(); datagramSocket.addEventListener( DatagramSocketDataEvent.DATA, dataReceived ); //Bind the socket to the local network interface and port datagramSocket.bind( localPort, localIP ); //Listen for incoming datagrams datagramSocket.receive(); //Create a message in a ByteArray var data:ByteArray = new ByteArray(); data.writeUTFBytes("Hello."); //Send the datagram message datagramSocket.send( data, 0, 0, targetIP, targetPort); } private function dataReceived( event:DatagramSocketDataEvent ):void { //Read the data from the datagram trace("Received from " + event.srcAddress + ":" + event.srcPort + "> " + event.data.readUTFBytes( event.data.bytesAvailable ) ); } }} 使用 UDP 通訊端時,請務必考慮以下方面:
如需詳細資訊,請參閱: IPv6 位址Flash Player 9.0.115.0 和更新版本都支援 IPv6 (網際網路通訊協定第 6 版)。IPv6 為「網際網路通訊協定」的其中一個版本,可支援 128 位元的位址 (與先前僅支援 32 位元的 IPv4 通訊協定相較之下,此為一大革新)。 您可能必須啟動您的網路介面上的 IPv6。 如需詳細資訊,請參閱存放資料之作業系統的「說明」。 如果主機系統上支援 IPv6,您可以在 URL 中指定數字的 IPv6 常值位址,並在前後加上方括弧 ([]),如下所示: [2001:db8:ccc3:ffff:0:444d:555e:666f] Flash Player 會根據下列規則,傳回 IPv6 常值:
Flash Player 傳回的 IPv6 值具有下列例外:
|
|