Sockets

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

Un socket es un tipo de conexión de red establecida entre dos procesos de ordenadores. Normalmente, los procesos se ejecutan en dos equipos distintos conectados a la misma red de Protocolo de Internet (IP). Sin embargo, los procesos conectados se pueden ejecutar en el mismo equipo si se utiliza una dirección IP especial “local host”.

Adobe Flash Player admite sockets de protocolo de control de transporte (TCP). Una aplicación de Flash Player se puede conectar a otro proceso que actúe como servidor de socket, pero no puede aceptar solicitudes de conexión entrantes de otros procesos. Dicho de otro modo, una aplicación de Flash Player se puede conectar a un servidor TCP, pero no puede hacer de servidor.

La API de Flash Player también contiene la clase XMLSocket. La clase XMLSocket utiliza un protocolo específico de Flash Player que permite intercambiar mensajes XML con un servidor que comprenda dicho protocolo. La clase XMLSocket se introdujo en ActionScript 1 y sigue admitiéndose para tener compatibilidad con versiones anteriores. En general, la clase Socket debe utilizarse para nuevas aplicaciones a no ser que se esté conectando a un servidor creado específicamente para comunicarse con XMLSockets de Flash.

Adobe AIR añade varias clases adicionales para programación de redes basadas en sockets. Las aplicaciones de AIR pueden actuar como servidores de socket TCP con la clase ServerSocket y pueden conectarse a servidores de socket que requieran seguridad SSL o TLS con la clase SecureSocket. Las aplicaciones de AIR también pueden enviar y recibir mensajes de protocolo de datagrama universal (UDP) con la clase DatagramSocket.

Sockets TCP

El protocolo TCP (Transmission Control Protocol) proporciona un modo de intercambiar mensajes a través de una conexión de red permanente. TCP garantiza que los mensajes enviados llegan en el orden adecuado (siempre y cuando no haya serios problemas de red). Las conexiones TCP requieren un “cliente” y un “servidor”. Flash Player puede crear sockets de cliente. Adobe AIR puede, además, crear sockets de servidor.

Las siguientes API de ActionScript proporcionan conexiones TCP:

  • Socket: permite que una aplicación cliente pueda conectarse a un servidor. La clase Socket no detecta conexiones entrantes.

  • SecureSocket (AIR): permite que una aplicación cliente pueda conectarse a un servidor de confianza e iniciar una comunicación cifrada.

  • ServerSocket (AIR): permite que una aplicación detecte conexiones entrantes y actúe como servidor.

  • XMLSocket: permite que una aplicación cliente se conecte a un servidor XMLSocket.

Sockets de cliente binarios

Una conexión de socket binario es similar a un socket XML, pero el cliente y el servidor no necesitan intercambiar mensajes XML. En lugar de eso, la conexión puede transferir datos como información binaria. Esto permite conectar una amplia gama de servicios, como servidores de correo (POP3, SMTP e IMAP) y servidores de noticias (NNTP).

Clase Socket

La clase Socket, introducida en ActionScript, permite que el código ActionScript realice conexiones de socket, y que lea y escriba datos binarios sin formato. La clase Socket resulta útil para interactuar con servidores que utilicen protocolos binarios. Se pueden utilizar conexiones de socket binario para escribir código que permita la interacción con varios protocolos de Internet distintos, como POP3, SMTP, IMAP y NNTP. Esto, a su vez, permite a las aplicaciones conectarse a servidores de correos y noticias.

Flash Player puede interactuar con un servidor directamente mediante el protocolo binario de dicho servidor. Algunos servidores utilizan el orden de bytes big-endian y otros emplean little-endian. La mayoría de los servidores de Internet utilizan big-endian, ya que es el "orden de bytes de la red". El orden de bytes littleEndian es popular porque la arquitectura Intel® x86 lo utiliza. Debe utilizarse el orden de bytes Endian que coincida con el orden de bytes del servidor que envía o recibe los datos. Todas las operaciones que se realizan mediante las interfaces IDataInput e IDataOutput, y las clases que implementan dichas interfaces (ByteArray, Socket y URLStream) se codifican de forma predeterminada en formato bigEndian. Esto supone que el byte más significativo va primero. El orden de bytes predeterminado se elige para que coincida con el de Java y con el orden de bytes de red oficial. Para cambiar entre el uso de orden de bytes bigEndian o littleEndian, se puede establecer la propiedad endian en Endian.BIG_ENDIAN o Endian.LITTLE_ENDIAN.

La clase Socket hereda todos los métodos definidos por las interfaces IDataInput e IDataOutput (ubicadas en el paquete flash.utils). Estos métodos se deben utilizar para escribir y leer desde el socket.

Para obtener más información, consulte:

Sockets de cliente seguros (AIR)

La clase SecureSocket se puede utilizar para conectarse a los servidores socket que utilicen la versión 4 de Secure Sockets Layer (SSLv4) o Transport Layer Security, versión 1 (TLSv1). Un socket seguro ofrece tres ventajas: autenticación del servidor, integridad de los datos y confidencialidad de los mensajes. El motor de ejecución de autentica un servidor utilizando el certificado del servidor y su relación con los certificados raíz o intermedios de la entidad emisora de certificados en el almacén de confianza del usuario. El motor de ejecución se basa en los algoritmos de criptografía utilizados por las implementaciones de protocolo SSL y TLS para proporcionar integridad de los datos y confidencialidad de los mensajes.

Cuando se realiza la conexión a un servidor utilizando el objeto SecureSocket, el motor de ejecución valida el certificado del servidor utilizando el almacén de confianza del certificado. En Windows y Mac, el sistema operativo proporciona el almacén de confianza. En Linux, el motor de ejecución de proporciona su propio almacén de confianza.

Si el certificado del servidor no es válido ni de confianza, el motor de ejecución distribuye un evento ioError. Se puede comprobar la propiedad serverCertificateStatus del objeto SecureSocket para determinar por qué se ha producido un error de validación. No existen previsiones para la comunicación con un servidor que no disponga de un certificado de confianza válido.

La clase CertificateStatus define constantes de cadena que representan los posibles resultados de validación:

  • Caducado: ha pasado la fecha de caducidad del certificado.

  • No válido: existen varios motivos por los que un certificado puede no ser válido. Por ejemplo, el certificado puede haber sido modificado, dañado o ser de tipo incorrecto.

  • Cadena no válida: uno o varios certificados de la cadena del servidor no son válidos.

  • Falta de coincidencia principal: el nombre de host del servidor y el nombre común del certificado no coinciden. Es decir, el servidor está utilizando el certificado incorrecto.

  • Revocado: la entidad emisora de certificados ha revocado el certificado.

  • De confianza: el certificado es válido y de confianza. Un objeto SecureSocket solo se puede conectar a un servidor que utilice un certificado válido y de confianza.

  • Desconocido: el objeto SecureSocket no ha validado aún el certificado. La propiedad serverCertificateStatus presenta este valor de estado antes de llamar a connect() y antes de que se distribuya un evento connect o ioError.

  • Firmantes que no son de confianza: el certificado no se “vincula” a un certificado raíz de confianza en el almacén de confianza del equipo cliente.

La comunicación con un objeto SecureSocket requiere que el servidor utilice un protocolo seguro y cuente con un certificado válido y de confianza. En otros aspectos, el uso de un objeto SecureSocket es el mismo que la utilización de un objeto Socket.

El objeto SecureSocket no se admite en todas las plataformas. Utilice la propiedad isSupported de la clase SecureSocket para comprobar si el motor de ejecución admite el uso del objeto SecureSocket en el equipo cliente actual.

Para obtener más información, consulte:

Ejemplo de socket TCP: Creación de un cliente Telnet

En el ejemplo de Telnet se muestran las técnicas para conectar con un servidor remoto y transmitir datos con la clase Socket. El ejemplo ilustra las técnicas siguientes:

  • Creación de un cliente Telnet personalizado mediante la clase Socket

  • Envío de texto al servidor remoto mediante un objeto ByteArray

  • Gestión de datos recibidos de un servidor remoto

Para obtener los archivos de la aplicación de este ejemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_es. Los archivos de la aplicación Telnet se encuentran en la carpeta Samples/Telnet. La aplicación consta de los siguientes archivos:

Archivo

Descripción

TelnetSocket.fla

o

TelnetSocket.mxml

El archivo principal de la aplicación formado por la interfaz de usuario de Flex (MXML) o de Flash (FLA).

TelnetSocket.as

Clase de documento que proporciona la lógica de la interfaz de usuario (solo Flash).

com/example/programmingas3/Telnet/Telnet.as

Proporciona la funcionalidad del cliente Telnet para la aplicación como, por ejemplo, la conexión a un servidor remoto y el envío, recepción y visualización de datos.

Información general de la aplicación de socket Telnet

El archivo principal TelnetSocket.mxml es responsable de crear la interfaz de usuario de toda la aplicación.

Además de la interfaz de usuario, este archivo también define dos métodos, login() y sendCommand(), para conectar el usuario al servidor especificado.

A continuación se muestra el código ActionScript del archivo de la aplicación principal:

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 = ""; 
}

La primera línea de código importa la clase Telnet del paquete com.example.programmingas.socket personalizado. La segunda línea de código declara una instancia de la clase Telnet, telnetClient, que se inicializará posteriormente mediante el método connect(). A continuación, se declara el método connect() e inicializa la variable telnetClient declarada previamente. Este método pasa el nombre del servidor Telnet especificado por el usuario, el puerto del servidor Telnet y una referencia a un componente TextArea de la lista de visualización, que se utiliza para mostrar las respuestas de texto del servidor de socket. Las dos últimas líneas del método connect() establecen la propiedad title de Panel y activan el componente Panel, que permite al usuario enviar datos al servidor remoto. El método final del archivo principal de la aplicación, sendCommand(), se utiliza para enviar los comandos del usuario al servidor remoto como un objeto ByteArray.

Información general de la clase Telnet

La clase Telnet es la responsable de conectar con el servidor Telnet remoto, y de enviar y recibir datos.

La clase Telnet declara las siguientes variables privadas:

private var serverURL:String; 
private var portNumber:int; 
private var socket:Socket; 
private var ta:TextArea; 
private var state:int = 0;

La primera variable, serverURL, contiene la dirección del servidor, especificada por el usuario, con la que se va a conectar.

La segunda variable, portNumber, es el número de puerto en el que se está ejecutando el servidor Telnet. De forma predeterminada, el servicio Telnet se ejecuta en el puerto 23.

La tercera variable, socket, es una instancia de Socket que intentará conectar con el servidor definido por las variables serverURL y portNumber.

La cuarta variable, ta, es una referencia a una instancia del componente TextArea en el escenario. Este componente se utiliza para mostrar las respuestas del servidor Telnet remoto o cualquier posible mensaje de error.

La última variable, state, es un valor numérico que se utiliza para determinar las opciones que admite el cliente Telnet.

Tal y como se ha visto previamente, se llama a la función constructora de la clase Telnet a través del método connect() en el archivo de la aplicación principal.

El constructor Telnet adopta tres parámetros: server, port y output. Los parámetros server y port especifican el nombre de servidor y el número de puerto donde se ejecuta el servidor Telnet. El parámetro final, output, es una referencia a una instancia del componente TextArea en el escenario, donde los usuarios verán la salida del servidor.

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(); 
    } 
}
Escritura de datos en un socket

Para escribir datos en una conexión de socket, es necesario llamar a cualquiera de los métodos de la clase Socket. Entre estos métodos de escritura se incluyen writeBoolean(), writeByte(), writeBytes() y writeDouble(), entre otros. Posteriormente, vacíe los datos en el búfer de salida con el método flush(). En el servidor Telnet, los datos se escriben en la conexión de socket mediante el método writeBytes(), que utiliza el conjunto de bytes como parámetro y lo envía al búfer de salida. La sintaxis del método writeBytesToSocket() es la siguiente:

public function writeBytesToSocket(ba:ByteArray):void 
{ 
    socket.writeBytes(ba); 
    socket.flush(); 
}

Este método se llama mediante el método sendCommand() del archivo de la aplicación principal.

Visualización de mensajes del servidor de socket

Cuando se recibe un mensaje del servidor de socket o se produce un evento, se llama al método personalizado msg(). Este método añade una cadena a TextArea en el escenario y llama a un método personalizado setScroll(), que desplaza el componente TextArea hasta la parte más baja. La sintaxis del método msg() es la siguiente:

private function msg(value:String):void 
{ 
    ta.text += value; 
    setScroll(); 
}

Si el contenido del componente TextArea no se desplaza automáticamente, el usuario deberá arrastrar manualmente las barras de desplazamiento en el área de texto para ver la última respuesta del servidor.

Desplazamiento de un componente TextArea

El método setScroll() contiene una sola línea de código ActionScript que desplaza verticalmente el contenido del componente TextArea para que el usuario pueda ver la última línea del texto devuelto. El siguiente fragmento de código muestra el método setScroll():

public function setScroll():void 
{ 
    ta.verticalScrollPosition = ta.maxVerticalScrollPosition; 
}

Este método establece la propiedad verticalScrollPosition, que es el número de línea de la fila superior de caracteres que se visualiza, con el valor de la propiedad maxVerticalScrollPosition.

Sockets XML

Un socket XML permite crear una conexión en un servidor remoto que permanece abierta hasta que se cierra explícitamente. Puede intercambiar datos de cadenas, como XML, entre el servidor y el cliente. Una ventaja de utilizar un servidor de socket XML es que el usuario no tiene que solicitar datos de forma explícita. El servidor envía datos sin esperar una solicitud, y puede enviar datos a cualquier cliente conectado.

En Flash Player y en contenido de Adobe AIR fuera del entorno limitado de la aplicación, las conexiones de socket XML requieren la presencia de un archivo de política de socket en el servidor de destino. Para obtener más información, consulte Controles de sitio web (archivos de política) y Conexión a sockets.

La clase XMLSocket no puede atravesar cortafuegos automáticamente, ya que, a diferencia del protocolo RTMP (Real-Time Messaging Protocol), XMLSocket no dispone de prestaciones de tunelación HTTP. Si es necesario utilizar tunelación HTTP, debe considerarse la posibilidad de utilizar Flash Remoting o Flash Media Server (que admite RTMP).

Las siguientes restricciones afectan a la forma y el lugar en que el contenido de Flash Player o de una aplicación de AIR puede utilizar un objeto XMLSocket para conectarse con el servidor fuera del entorno limitado de seguridad de la aplicación:

  • Para el contenido fuera del entorno limitado de seguridad de la aplicación, el método XMLSocket.connect() solo puede conectarse a números de puerto TCP superiores o iguales a 1024. Como consecuencia de esta limitación, los dominios del servidor que se comunica con el objeto XMLSocket también deben asignarse a números de puerto superiores o iguales a 1024. Los números de puerto inferiores a 1024 suelen utilizarse para servicios del sistema como FTP (21), Telnet (23), SMTP (25), HTTP (80) y POP3 (110), por lo que los objetos XMLSocket no pueden utilizar estos puertos por razones de seguridad. La restricción de número de puerto limita la posibilidad de que se pueda acceder y hacer un uso indebido de estos recursos.

  • Para el contenido fuera del entorno limitado de seguridad de la aplicación, el método XMLSocket.connect() solo puede conectarse a equipos del mismo dominio en que reside el contenido. (Esta restricción es idéntica a la incluida en las reglas de seguridad establecidas para URLLoader.load().) Para conectar con un dominio de servidor que se ejecuta en un dominio diferente a aquel en el que reside el contenido, puede crear un archivo de política de seguridad de varios dominios que permita el acceso desde dominios específicos. Para más información sobre archivos de política de varios dominios, consulte Seguridad en AIR.

Nota: la configuración de un servidor para que se comunique con el objeto XMLSocket puede resultar compleja. Si la aplicación no requiere interactividad en tiempo real, utilice la clase URLLoader en vez de la clase XMLSocket.

Puede utilizar los métodos XMLSocket.connect() y XMLSocket.send() de la clase XMLSocket para transferir XML desde y hacia un servidor a través de una conexión de socket. El método XMLSocket.connect() establece una conexión de socket con un puerto de servidor web. El método XMLSocket.end() pasa un objeto XML al servidor especificado en la conexión de socket.

Cuando se invoca el método XMLSocket.connect(), la aplicación abre una conexión TCP/IP con el servidor y la mantiene abierta hasta que produce una de las condiciones que se indican a continuación:

  • Se llama al método XMLSocket.close() de la clase XMLSocket.

  • No existen más referencias al objeto XMLSocket.

  • Se sale de Flash Player.

  • Se interrumpe la conexión (por ejemplo, se desconecta el módem).

Conexión con un servidor con la clase XMLSocket

Para crear una conexión de socket debe crear una aplicación de servidor que espere la petición de conexión de socket y envíe una respuesta a Flash Player o a la aplicación de AIR. Este tipo de aplicación de servidor puede escribirse en AIR o en un lenguaje de programación como Java, Python o Perl. Para utilizar la clase XMLSocket, el equipo servidor debe ejecutar un dominio que entienda el protocolo simple utilizado por la clase XMLSocket:

  • Los mensajes XML se envían a través de una conexión de socket ininterrumpida TCP/IP dúplex.

  • Cada mensaje XML es un documento XML completo terminado en un byte cero (0).

  • Pueden enviarse y recibirse un número ilimitado de mensajes XML a través de una misma conexión XMLSocket.

Creación y conexión de un servidor de socket XML de Java

El siguiente código muestra un sencillo servidor XMLSocket escrito en Java que acepta conexiones entrantes y muestra los mensajes recibidos en la ventana de símbolo del sistema. De forma predeterminada, se crea un nuevo servidor en el puerto 8080 del equipo local, aunque se puede especificar otro número de puerto cuando se inicia el servidor desde la línea de comandos.

Cree un nuevo documento de texto y añada el siguiente código:

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); 
    } 
}

Guarde el documento en el disco duro como SimpleServer.java y compílelo con la ayuda de un compilador de Java para crear un archivo de clase de Java denominado SimpleServer.class.

Para iniciar el servidor XMLSocket, abra un símbolo del sistema y escriba java SimpleServer. El archivo SimpleServer.class puede almacenarse en cualquier lugar del equipo local o la red; no es necesario que esté en el directorio raíz del servidor web.

Si no puede iniciar el servidor porque los archivos no se encuentran en la ruta de clases de Java, intente iniciar el servidor con java -classpath. SimpleServer.

Para conectarse a XMLSocket desde la aplicación , es necesario crear una nueva instancia de la clase XMLSocket y llamar al método XMLSocket.connect(), pasando un nombre de host y un número de puerto, del siguiente modo:

var xmlsock:XMLSocket = new XMLSocket(); 
xmlsock.connect("127.0.0.1", 8080);

Cuando se reciben datos del servidor, se distribuye el evento data (flash.events.DataEvent.DATA):

xmlsock.addEventListener(DataEvent.DATA, onData); 
private function onData(event:DataEvent):void 
{ 
    trace("[" + event.type + "] " + event.data); 
}

Para enviar datos al servidor XMLSocket, se utiliza el método XMLSocket.send() y se pasa una cadena u objeto XML. Flash Player convierte el parámetro suministrado en un objeto String y envía el contenido al servidor XMLSocket, seguido de un byte cero (0):

xmlsock.send(xmlFormattedData);

El método XMLSocket.send() no devuelve ningún valor que indique si los datos se han transmitido correctamente. Si se produce un error al intentar enviar datos, se emite un error IOError.

Cada mensaje que se envía al servidor de socket XML debe terminar con un carácter de nueva línea (\n).

Para obtener más información, consulte XMLSocket.

Sockets de servidor

Utilice la clase ServerSocket para permitir que otro proceso se conecte a la aplicación utilizando un socket TCP (Transport Control Protocol). El proceso de conexión se puede ejecutar en el equipo local o en otro equipo conectado a la red. Cuando un objeto recibe una solicitud de conexión, distribuye un evento connect. El objeto ServerSocketConnectEvent distribuido con el evento contiene un objeto Socket. Este objeto Socket se puede emplear para una comunicación posterior con los demás procesos.

Para detectar conexiones de socket entrantes:

  1. Cree un objeto ServerSocket y vincúlelo con un puerto local.

  2. Añada detectores de eventos para el evento connect.

  3. Llamada al método listen()

  4. Responda al evento connect, lo que proporciona un objeto Socket para cada conexión entrante.

El objeto ServerSocket sigue detectando conexiones adicionales hasta que se llama al método close().

En el siguiente ejemplo de código se muestra cómo crear una aplicación de servidor de socket. En el ejemplo se detectan las conexiones entrantes en el puerto 8087. Cuando se recibe una conexión, el ejemplo envía un mensaje (cadena “Connected.”) al socket de cliente. Por lo tanto, el servidor reproduce todos los mensajes recibidos del cliente.

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." ); 
        } 
}}

Para obtener más información, consulte:

Sockets UDP (AIR)

El protocolo UDP (Universal Datagram Protocol) proporciona un modo de intercambiar mensajes a través de una conexión de red sin estado. UDP no garantiza que los mensajes se distribuyan en orden o incluso que los mensajes se envíen en modo alguno. Con UDP, el código de red del sistema operativo suele emplear menos tiempo en la identificación, seguimiento y reconocimiento de mensajes. De este modo, los mensajes UDP suelen llegar a la aplicación de destino con un retraso menor que los mensajes TCP.

La comunicación del socket UDP resulta útil cuando se debe enviar información en tiempo real como, por ejemplo, actualizaciones de posición en un juego o paquetes de sonido en una aplicación de chat de audio. En estas aplicaciones, se tolera cierta pérdida de datos y una latencia de transmisión baja es más importante que la llegada garantizada. Para la mayoría de los demás objetivos, los sockets TCP representan un mejor opción.

La aplicación de AIR puede enviar y recibir mensajes UDP con las clases DatagramSocket y DatagramSocketDataEvent. Para enviar o recibir un mensaje UDP:

  1. Cree un objeto DatagramSocket.

  2. Añada un detector de eventos al evento data.

  3. Enlace el socket a un puerto y dirección IP local utilizando el método bind().

  4. Envíe mensajes llamando al método send() y transmitiendo el puerto y la dirección IP del equipo de destino.

  5. Reciba mensajes respondiendo al evento data. El objeto DatagramSocketDataEvent distribuido para este evento contiene un objeto ByteArray que incluye los datos del mensaje.

El siguiente ejemplo de código muestra el modo en que una aplicación puede enviar y recibir mensajes UDP. El ejemplo envía un solo mensaje que contiene la cadena, “Hello.”, al equipo de destino. También realiza un seguimiento del contenido de todos los mensajes recibidos.

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 ) ); 
    } 
}}

Al emplear sockets UDP se debe tener en cuenta lo siguiente:

  • Un solo paquete de datos no puede ser superior a la unidad de transmisión máxima más pequeña (MTU) de la interfaz de red o cualquier nodo de red entre el remitente y el destinatario. Todos los datos del objeto ByteArray transmitidos al método send() se envían como un solo paquete. (En TCP, los mensajes grandes se dividen en paquetes independientes.)

  • No existe conexión entre el remitente y el destino. Los mensajes se descartan sin error si el destino no existe o no dispone de un detector activo en el puerto especificado.

  • Si se utiliza el método connect(), los mensajes enviados desde otros recursos se omitirán. Una conexión UDP solo proporciona el filtrado de paquetes adecuado. No significa que sea necesariamente un proceso de detección válido en la dirección y el puerto de destino.

  • El tráfico UDP puede sobrecargar una red. Es posible que los administradores de red deban implementar controles de calidad del servicio si se produce la saturación en la red. (TCP dispone de control de tráfico integrado para reducir el impacto de la saturación de la red.)

Para obtener más información, consulte:

Direcciones IPv6

Flash Player 9.0.115.0 y las versiones posteriores admiten IPv6 (Protocolo de Internet versión 6). IPv6 es una versión del Protocolo de Internet que admite direcciones de 128 bits (una mejora con respecto al protocolo anterior IPv4 que admite direcciones de 32 bits). Es posible que tenga que activar IPv6 en sus interfaces de red. Para más información, consulte la Ayuda del sistema operativo que aloja los datos.

Si se admite IPv6 en el sistema de host, puede especificar direcciones literales numéricas de IPv6 en URL entre corchetes ([]), como se muestra a continuación:

[2001:db8:ccc3:ffff:0:444d:555e:666f]

Flash Player devuelve valores IPv6 literales, en función de las siguiente reglas:

  • Flash Player devuelve el formulario largo de la cadena para las direcciones IPv6.

  • El valor IP no tiene abreviaciones de dos puntos dobles.

  • Los dígitos hexadecimales solo aparecen en minúscula.

  • Las direcciones IPv6 aparecen entre corchetes ([]).

  • Cada cuarteto de direcciones se representa como dígitos hexadecimales de 0 a 4, donde se omiten los primeros ceros.

  • Un cuarteto de direcciones de todos los ceros aparece como un solo cero (no dos puntos dobles), excepto donde se indica en la siguiente lista de excepciones.

Los valores IPv6 que devuelve Flash Player presentan las siguientes excepciones:

  • Una dirección IPv6 no especificada (todos los ceros) aparece como [::].

  • La dirección IPv6 de localhost o bucle invertido se presenta como [::1].

  • Las direcciones asignadas a IPv4 (convertidas a IPv6) se presentan como [::ffff:a.b.c.d], siendo a.b.c.d un valor típico decimal con puntos de IPv4.

  • Las direcciones compatibles con IPv4 aparecen como [::a.b.c.d], siendo a.b.c.d un valor típico decimal con puntos de IPv4.