套接字

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 连接:

  • 套接字 — 允许客户端应用程序连接到服务器。Socket 类无法侦听传入连接。

  • SecureSocket (AIR) — 允许客户端应用程序连接到受信任服务器并进行加密通信。

  • ServerSocket (AIR) — 允许应用程序侦听传入连接并用作服务器。

  • XMLSocket — 允许客户端应用程序连接到 XMLSocket 服务器。

二进制客户端套接字

二进制套接字连接与 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_ENDIANEndian.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 对象尚未验证证书。serverCertificateStatus 属性在您调用 connect() 和调度 connectioError 事件之前具有此状态值。

  • 不受信任的签名者 — 证书不能“链接”到客户端计算机的信任存储区中的受信任根证书。

与 SecureSocket 对象通信要求服务器使用安全协议,并包含有效的受信任证书。在其他方面,使用 SecureSocket 对象与使用 Socket 对象是相同的。

并不是所有平台都支持 SecureSocket 对象。使用 SecureSocket 类 isSupported 属性测试运行时是否支持在当前客户端计算机上使用 SecureSocket 对象。

有关详细信息,请参阅:

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.connect() 方法只能连接到端口号大于或等于 1024 的 TCP 端口。这种限制所带来的后果之一是,向与 XMLSocket 对象通信的服务器守护程序分配的端口号也必须大于等于 1024。端口号小于 1024 的端口通常用于系统服务,例如 FTP (21)、Telnet (23)、SMTP (25)、HTTP (80) 和 POP3 (110),因此,出于安全方面的考虑,禁止 XMLSocket 对象使用这些端口。这种端口号方面的限制可以减少不恰当地访问和滥用这些资源的可能性。

  • 对于应用程序安全沙箱外部的内容,XMLSocket.connect() 方法只能连接到该内容所在的同一域中的计算机。(此限制与 URLLoader.load() 的安全规则相同。)若要连接到在内容所在域之外的其他域中运行的服务器守护程序,可以在该服务器上创建一个允许从特定域进行访问的跨域策略文件。有关跨域策略文件的详细信息,请参阅 AIR 安全性

注: 将服务器设置为与 XMLSocket 对象进行通信可能会遇到一些困难。如果您的应用程序不需要进行实时交互,请使用 URLLoader 类,而不要使用 XMLSocket 类。

可以使用 XMLSocket 类的 XMLSocket.connect()XMLSocket.send() 方法,通过套接字连接与服务器之间传输 XML。XMLSocket.connect() 方法与 Web 服务器端口建立套接字连接。XMLSocket.send() 方法将 XML 对象传递给套接字连接中指定的服务器。

当调用 XMLSocket.connect() 方法时,应用程序会打开到服务器的 TCP/IP 连接并使该连接保持打开状态,直到出现下列情况之一:

  • XMLSocket 类的 XMLSocket.close() 方法被调用。

  • 对 XMLSocket 对象的引用不再存在。

  • 连接中断(例如,调制解调器断开连接)。

使用 XMLSocket 类连接到服务器

要创建套接字连接,必须创建服务器端应用程序以等待套接字连接请求,并将响应发送到 Flash Player 或 AIR 应用程序。此类服务器端应用程序可使用 AIR 或其他编程语言(如 Java、Python 或 Perl)编写。要使用 XMLSocket 类,服务器计算机必须运行可识别 XMLSocket 类使用的简单协议的守护程序:

  • XML 消息通过全双工 TCP/IP 流套接字连接发送。

  • 每个 XML 消息都是一个完整的 XML 文档,以一个零 (0) 字节结束。

  • 通过 XMLSocket 连接发送和接收的 XML 消息的数量没有限制。

服务器套接字

使用 ServerSocket 类可以允许其他进程使用传输控制协议 (TCP) 套接字连接到您的应用程序。可以在本地计算机或另一台网络连接的计算机上运行连接进程。当 ServerSocket 对象收到连接请求时,会调度 connect 事件。该事件调度的 ServerSocketConnectEvent 对象包含 Socket 对象。您可以使用此 Socket 对象与其他进程进行后续通信。

要侦听传入的套接字连接,请执行以下操作:

  1. 创建一个 ServerSocket 对象并将其绑定到本地端口

  2. connect 事件添加事件侦听器

  3. 调用 listen() 方法

  4. 响应 connect 事件,它为每个传入连接提供 Socket 对象

ServerSocket 对象在您调用 close() 方法之前会继续侦听新连接。

以下代码示例说明了如何创建套接字服务器应用程序。该示例侦听端口 8087 上的传入连接。收到连接时,此示例会将消息(字符串“Connected”)发送给客户端套接字。此后,服务器会将任何收到的消息回显给客户端。

<html> 
<head> 
<script src="AIRAliases.js"></script> 
<script language="javascript"> 
        var serverSocket; 
        var clientSockets = new Array(); 
        function startServer() 
        { 
            try 
            { 
                // Create the server socket 
                serverSocket = new air.ServerSocket(); 
                 
                // Add the event listener 
                serverSocket.addEventListener( air.Event.CONNECT, connectHandler ); 
                serverSocket.addEventListener( air.Event.CLOSE, onClose ); 
                 
                // Bind to local port 8087 
                serverSocket.bind( 8087, "127.0.0.1" ); 
                 
                // Listen for connections 
                serverSocket.listen(); 
                air.trace( "Listening on " + serverSocket.localPort ); 
            } 
            catch( e ) 
            { 
                air.trace( e ); 
            } 
        } 
        function connectHandler( event ) 
        { 
            //The socket is provided by the event object 
            var socket = event.socket; 
            clientSockets.push( socket ); 
             
            socket.addEventListener( air.ProgressEvent.SOCKET_DATA, socketDataHandler); 
            socket.addEventListener( air.Event.CLOSE, onClientClose ); 
            socket.addEventListener( air.IOErrorEvent.IO_ERROR, onIOError ); 
             
            //Send a connect message 
            socket.writeUTFBytes("Connected."); 
            socket.flush(); 
             
            air.trace( "Sending connect message" ); 
        } 
         
        function socketDataHandler( event ) 
        { 
            var socket = event.target 
                 
            //Read the message from the socket 
            var message = socket.readUTFBytes( socket.bytesAvailable ); 
            air.trace( "Received: " + message); 
            // Echo the received message back to the sender 
            message = "Echo -- " + message; 
            socket.writeUTFBytes( message ); 
            socket.flush(); 
            air.trace( "Sending: " + message ); 
        } 
         
        function onClientClose( event ) 
        { 
            air.trace( "Connection to client closed." ); 
            //Should also remove from clientSockets array... 
        } 
        function onIOError( errorEvent ) 
        { 
            air.trace( "IOError: " + errorEvent.text ); 
        } 
        function onClose( event ) 
        { 
            air.trace( "Server socket closed by OS." ); 
        } 
</script> 
</head> 
<body onload="startServer()"> 
</body> 
</html>

有关详细信息,请参阅:

UDP 套接字 (AIR)

通用数据报协议 (UDP) 提供了一种通过无状态网络连接交换消息的方法。UDP 无法确保消息按顺序传送,甚至无法确保消息的传送。使用 UDP,操作系统的网络代码通常在封送、跟踪和确认消息上将花费更少的时间。因此,通常 UDP 消息到达目标应用程序的延迟比 TCP 消息到达目标应用程序的延迟要短。

在必须发送实时信息(例如游戏中的位置更新或音频聊天应用程序中的声音数据包)时,UDP 套接字通信很有用。在此类应用程序中,丢失一些数据是可以接受的,并且低传输延迟比保证及时到达更重要。对于几乎所有其他目的,TCP 套接字是更好的选择。

AIR 应用程序可以使用 DatagramSocket 和 DatagramSocketDataEvent 类发送和接收 UDP 消息。要发送或接收 UDP 消息,请执行以下操作:

  1. 创建一个 DatagramSocket 对象

  2. data 事件添加事件侦听器

  3. 使用 bind() 方法将套接字绑定到本地 IP 地址和端口

  4. 通过调用 send() 方法发送消息,传递目标计算机的 IP 地址和端口

  5. 通过响应 data 事件接收消息。为此事件调度的 DatagramSocketDataEvent 对象包含一个 ByteArray 对象,该对象中包含消息数据。

以下代码示例说明应用程序如何发送和接收 UDP 消息。此示例将包含字符串“Hello”的单一消息发送到目标计算机。它还跟踪接收的任何消息内容。

<html> 
<head> 
<script src="AIRAliases.js"></script> 
<script language="javascript"> 
    var datagramSocket; 
     
    //The IP and port for this computer 
    var localIP = "192.168.0.1"; 
    var localPort = 55555; 
     
    //The IP and port for the target computer 
    var targetIP = "192.168.0.2"; 
    var targetPort = 55555; 
     
    function createDatagramSocket() 
    { 
        //Create the socket 
        datagramSocket = new air.DatagramSocket(); 
        datagramSocket.addEventListener( air.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 = new air.ByteArray(); 
        data.writeUTFBytes("Hello."); 
         
        //Send the datagram message 
        datagramSocket.send( data, 0, 0, targetIP, targetPort); 
    } 
     
    function dataReceived( event ) 
    { 
        //Read the data from the datagram 
        air.trace("Received from " + event.srcAddress + ":" + event.srcPort + "> " + 
            event.data.readUTFBytes( event.data.bytesAvailable ) ); 
    } 
</script> 
</head> 
<body onload="createDatagramSocket()"> 
</body> 
</html>

使用 UDP 套接字时,请记住下列注意事项:

  • 单一数据包不能大于网络接口或发送方和接收方之间任何网络节点的最大传输单位 (MTU) 中最小的那一个。传递到 send() 方法的 ByteArray 对象中的所有数据都将作为单一数据包发送。(在 TCP 中,较大的消息被分为几个单独的包。)

  • 发送方和目标之间不存在信号交换。如果目标不存在或指定端口上没有活动侦听器,则会丢弃消息且不会报错。

  • 使用 connect() 方法时,将忽略从其他源发送的消息。UDP 连接仅提供方便的数据包过滤。这并不意味着目标地址和端口上必须存在有效的侦听进程。

  • UDP 流量可以造成网络拥塞。如果发生网络拥塞,网络管理员可能需要实现服务质量控制。(TCP 有内置的流量控制来减少网络拥塞的影响。)

有关详细信息,请参阅:

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 地址字符串。

  • IP 值没有双冒号缩写词。

  • 十六进制数字全小写。

  • IPv6 地址包含在中括号 ([]) 中。

  • 每个四重地址都输出为 0 到 4 个十六进制数字(省略前导零)。

  • 内容全为零的四重地址输出为单个零(而不是双冒号),下表所列例外情况除外。

Flash Player 返回的 IPv6 值具有以下例外:

  • 未指定的 IPv6 地址(内容全为零)输出为 [::]。

  • 环回或本地主机 IPv6 地址输出为 [::1]。

  • IPv4 映射(转换为 IPv6)地址输出为 [::ffff:a.b.c.d],其中 a.b.c.d 为典型的 IPv4 点分十进制值。

  • IPv4 兼容地址输出为 [::a.b.c.d],其中 a.b.c.d 为典型的 IPv4 点分十进制值。