套接字Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本 套接字是在两个计算机进程之间建立的一种网络连接类型。通常,这些进程在两台连接到相同 Internet 协议 (IP) 网络的不同计算机上运行。然而,连接的进程可以在使用特定“本地主机”IP 地址的同一台计算机上运行。 Adobe Flash Player 支持客户端传输控制协议 (TCP) 套接字。Flash Player 应用程序可以作为套接字服务器连接到其他进程,但是不能接受来自其他进程的传入连接请求。换句话说,Flash Player 应用程序可以连接到 TCP 服务器,但不能用作 TCP 服务器。 Flash Player API 也包含 XMLSocket 类。XMLSocket 类使用 Flash Player 特定的协议,通过该协议,您可以与识别该协议的服务器交换 XML 消息。ActionScript 1 中引入了 XMLSocket 类,该类现在仍然受支持以提供向后兼容性。通常,除非连接到特别创建以与 Flash XMLSocket 进行通信的服务器,否则 Socket 类应该用于新应用程序。 Adobe AIR 添加了多个用于基于套接字的网络编程的附加类。借助 ServerSocket 类,AIR 应用程序可以用作 TCP 套接字服务器,并可以连接到要求 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 类非常有用。使用二进制套接字连接,您可以编写与多个不同的 Internet 协议(例如 POP3、SMTP、IMAP 和 NNTP)进行交互的代码。这种交互进而又使您的应用程序可以连接到邮件服务器和新闻服务器。 Flash Player 可通过使用服务器的二进制协议直接与该服务器连接。某些服务器使用 big-endian 字节顺序,某些服务器则使用 little-endian 字节顺序。Internet 上的大多数服务器使用 big-endian 字节顺序,因为“网络字节顺序”为 big-endian。little-endian 字节顺序很常用,因为 Intel® x86 体系结构使用该字节顺序。您应使用与收发数据的服务器的字节顺序相匹配的 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 包中)。必须使用这些方法写入和读取套接字。 有关详细信息,请参阅: 安全客户端套接字 (AIR)您可以使用 SecureSocket 类连接到使用第 4 版安全套接字层 (SSLv4) 或第 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_cn。可以在 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() 方法的最后两行设置 Panel 的 title 属性并启用 Panel 组件,该组件允许用户将数据发送到远程服务器。主应用程序文件中的最后一个方法 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() 方法调用的。 XML 套接字通过 XML 套接字,可以创建与远程服务器的连接,且该服务器在显式关闭之前始终保持打开状态。您可以在服务器和客户端之间交换字符串数据,如 XML。使用 XML 套接字服务器的优点之一是客户端不需要显式请求数据。服务器无需等待请求即可发送数据,并且可以将数据发送到每个已连接的客户端。 在应用程序沙箱外的 Flash Player 和 Adobe AIR 内容中,XML 套接字连接要求在目标服务器上提供套接字策略文件。有关详细信息,请参阅网站控制(策略文件)和连接到套接字。 XMLSocket 类不能自动穿过防火墙,因为 XMLSocket 没有 HTTP 隧道功能(这与实时消息传递协议 (RTMP) 不同)。如果您需要使用 HTTP 隧道,应考虑改用 Flash Remoting 或 Flash Media Server(支持 RTMP)。 对于应用程序安全沙箱外的 Flash Player 或 AIR 应用程序中的内容使用 XMLSocket 对象连接到服务器的方式及位置,规定了下列限制:
注: 将服务器设置为与 XMLSocket 对象进行通信可能会遇到一些困难。如果您的应用程序不需要进行实时交互,请使用 URLLoader 类,而不要使用 XMLSocket 类。
可以使用 XMLSocket 类的 XMLSocket.connect() 和 XMLSocket.send() 方法,通过套接字连接与服务器之间传输 XML。XMLSocket.connect() 方法与 Web 服务器端口建立套接字连接。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 文件可以位于本地计算机或网络上的任何位置,不需要放置在 Web 服务器的根目录中。 如果由于文件没有位于 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 对象,并将内容发送到 XMLSocket 服务器(后跟零 (0) 字节): xmlsock.send(xmlFormattedData); XMLSocket.send() 方法不返回指示数据是否成功传输的值。如果尝试发送数据时发生错误,将引发 IOError 错误。 发送到 XML 套接字服务器的每条消息必须以换行符 (\n) 结束。 有关详细信息,请参阅 XMLSocket。 服务器套接字使用 ServerSocket 类可以允许其他进程使用传输控制协议 (TCP) 套接字连接到您的应用程序。可以在本地计算机或另一台网络连接的计算机上运行连接进程。当 ServerSocket 对象收到连接请求时,会调度 connect 事件。该事件调度的 ServerSocketConnectEvent 对象包含 Socket 对象。您可以使用此 Socket 对象与其他进程进行后续通信。 要侦听传入的套接字连接,请执行以下操作:
ServerSocket 对象在您调用 close() 方法之前会继续侦听新连接。 以下代码示例说明了如何创建套接字服务器应用程序。该示例侦听端口 8087 上的传入连接。收到连接时,此示例会将消息(字符串“Connected”)发送给客户端套接字。此后,服务器会将任何收到的消息回显给客户端。 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(Internet 协议版本 6)。IPv6 是支持 128 位地址的 Internet 协议版本(它是支持 32 位地址的早期 IPv4 协议的改进版本)。 您可能需要在网络接口中激活 IPv6。 有关详细信息,请参阅承载数据的操作系统的帮助。 如果承载系统中支持 IPv6,您可以在用中括号 ([]) 括起的 URL 中指定数字 IPv6 文本地址,如下所示: [2001:db8:ccc3:ffff:0:444d:555e:666f] Flash Player 根据以下规则返回 IPv6 字面值:
Flash Player 返回的 IPv6 值具有以下例外:
|
|