Table of Contents

XMLSocket Class Flash 5

support for a persistent client/server TCP/IP connection

Constructor

new XMLSocket()

Methods

close( )

Terminate an open connection to a server application.

connect( )

Attempt to establish a new connection to a server application.

send( )

Send an XML object hierarchy to a server application as a string.

Event handlers

onClose( )

Executes when the server terminates the connection.

onConnect( )

Executes when a connection attempt completes.

onData( )

Executes when data is received but has not yet been parsed as XML.

onXML( )

Executes when data has been received and parsed into an XML object hierarchy.

Description

The majority of connections between Flash and a server have a very short life span. When Flash requests external data via loadMovie( ), LoadVars, or XML, a temporary communication channel is established. Data is sent over that channel, and then the channel is terminated. This kind of short-term communication has many useful applications, but it is also limited in two important ways:

As of Flash 5, we can overcome these limitations with the XMLSocket class, which allows us to open a persistent communication link between a server application and Flash. We use XMLSocket to develop systems that require frequent server updates, such as a chat room or a networked multiplayer game.

In order to connect to a remote application using XMLSocket, we must first create and store an XMLSocket object, like this:

mySocket = new XMLSocket();

Next, we invoke the connect( ) method, which asks Flash to establish a communication link with the remote application. For example:

mySocket.connect("http://www.myserver.com", 8000);

Once a connection is established, the XMLSocket object acts as a transmitter/receiver. We send XML-formatted data to the remote application by invoking the socket's send( ) method, and we know that we've received XML-formatted data when the socket's onXML( ) event is triggered.

A server application used with an XMLSocket object must:

Typically, server applications are created by server-side programmers, not Flash programmers. Some of the available Flash-compatible socket servers are listed in Table 18-29.

Table 18-29. Flash-compatible socket servers

Name

Description

License

Location

moockComm

A light-weight reference implementation, written in Java

Free

http://www.moock.org/chat/moockComm.zip

aquaServer

A light-weight reference implementation, written in Java

Free

http://www.figleaf.com/development/flash5/aquaserver.zip

Unity

A full-featured rooms-based server written in Java

Pay

http://www.moock.org/unity

Fortress

A mature, heavy-duty socket server

Pay

http://www.xadra.com/products/main.html

ElectroServer

A full-featured, real-world tested socket server

Pay

http://www.electrotank.com/ElectroServer

An XMLSocket connection stays open until one of the following occurs:

The XMLSocket class also provides four event handlers—onClose( ), onConnect( ), onData( ), and onXML( )—that allow us to monitor the status of an open connection.

If you fail to define callback handlers for the onClose and onConnect properties, you won't be able to perform any error checking or provide any feedback about a connection attempt. If you fail to define a callback handler for your onXML property, you won't be notified when the socket receives data from a server-side application, nor will you be able to retrieve such data.

For extensive information on XMLSocket development, see:

http://www.moock.org/unity
http://hotwired.lycos.com/webmonkey/multimedia/shockwave_flash/tutorials/tutorial9.html

Note that as of Flash 6, real-time communication can also be implemented with Macromedia Flash Communication Server MX (Comm Server). Comm Server does not use XML; rather, it uses the custom RMTP protocol for seamless remote execution of ActionScript code. Furthermore, Comm Server supports video and audio streaming. For more information, see:

http://www.macromedia.com/software/flashcom/

Example

Example 18-10 defines an XMLSocket subclass, SocketController, which wraps the use of the XMLSocket class into a series of convenient methods and event handlers. The class is saved in the file SocketController.as and is available at the online Code Depot. Example 18-11 shows how to use SocketController to create a very simple chat application.

Example 18-10. The SocketController class
/*
 * SocketController Class. Extends XMLSocket.
 *   Version: 1.0.0
 *   Desc: Provides services for communicating with a socket server.
 *
 * Methods
 *  doConnect()             -connect to server
 *  setServer()             -set server host/port
 *  killConnect()           -disconnect from server
 *  send()                  -send XML to the server
 *
 * Event Handlers
 *  onConnectFailure()      -when connect attempt fails
 *  onConnectSuccess()      -when connect attempt succeeds
 *  onServerKillConnect()   -when server kills connection
 *  onClientKillConnect()   -when Flash kills connection
 *  onXML()                 -when new XML arrives
 */
   
// Set superclass to XMLSocket.
SocketController.prototype = new XMLSocket();
   
// Class constructor
function SocketController (host, port) {
  // Instance properties
  this.host = null;
  this.port = 0;
   
  // Initialization: Assign provided values to host and port properties.
  if (arguments.length > 1) {
    this.setServer(host, port);
  }
}
   
// Instance Methods
/*
 * Attempt to connect to the server.
 */
SocketController.prototype.doConnect = function () {
  // If there's no valid server defined, then fail
  if (this.host =  = null || this.port < 1024) {
    trace("Connection attempt aborted: invalid host or port.");
    this.onConnectFailure();
    return false;
  } else {
    // Otherwise, attempt to connect (connect returns true if the
    // initial stage of connection succeeds).
    var connectSuccess = this.connect(this.host, this.port);
  }
   
  // If the initial connection stage succeeds...
  if (connectSuccess) {
    // ...wait for the onConnect() event to fire.
    trace("Initial connection succeeded. Awaiting server response...");
  } else {
    // ...otherwise, connect() returned false, so we didn't
    // establish a connection.
    trace("Initial connection failed");
    // Invoke the user-defined callback for connect failure.
    this.onConnectFailure();
  }
};
   
/*
 * Set the host and port of the server.
 */
SocketController.prototype.setServer = function (host, port) {
  // Error handling. Host must be a string, 
  // and port must be a number over 1023.
  if (typeof host != "string"
      || typeof port != "number"
      || (typeof port =  = "number" && port < 1024)) {
    trace("Server assignment failed: invalid host or port.");
    // Reset host and port.
    this.host = null;
    this.port = 0;
    return false;
  }
   
  // Host and port are valid, so assign them.
  trace("Server set to: " + host + " " + port);
  this.host = host;
  this.port = port;
};
   
/*
 * Callback to respond to the completion of a connection attempt.
 */
SocketController.prototype.onConnect = function (success) {
  // If onConnect( )'s success argument is true, 
  // connection has been established.
  if (success) {
    trace("Connection to: " + this.host + " " + this.port + " established");
    // Invoke the user-defined callback for connection success.
    this.onConnectSuccess();
  } else {
    // success was false, so the connection was not established.
    trace("Connection to: " + this.host + " "
                      + this.port + " could not be established");
    // Invoke the user-defined callback for connection failure.
    this.onConnectFailure();
  }
};
   
/*
 * Callback invoked when server kills the connection.
 */
SocketController.prototype.onClose = function () {
  trace("The server has terminated the connection.");
  // Invoke the user-defined callback for server disconnect
  this.onServerKillConnect();
};
   
/*
 * Closes the connection to the server manually.
 */
SocketController.prototype.killConnect = function () {
  trace("Closing current connection.");
  this.close();
  // Invoke the user-defined callback for client disconnect
  this.onClientKillConnect();
};

Example 18-11 demonstrates the use of SocketController with a simple chat application.

Example 18-11. A simple SocketController chat app
// A Simple Chat App
// Load SocketController class
#include "SocketController.as"
// Start the show
main();
   
// The chat application
function main () {
  // Store a portable reference to the current timeline
  _global.chatMain = this;
   
  // Create sending text field
  chatMain.createTextField("send_txt", 1, 100, 100, 300, 20);
  chatMain.send_txt.border = true;
  chatMain.send_txt.type = "input";
   
  // Create output text field
  chatMain.createTextField("output_txt", 2, 100, 130, 300, 200);
  chatMain.output_txt.border = true;
  chatMain.output_txt.type = "dynamic";
   
  // Create the SocketController instance and connect to the server
  chatController = new SocketController();
  chatController.setServer("moock.org", 8050);
  chatController.doConnect();
   
  // Invoked when a message is received
  chatController.onXML = function (src) {
    trace("Received XML: " + src);
    var message = src.firstChild.firstChild.nodeValue;
    chatMain.output_txt.text +=  message + "\n";
  };
   
  // Invoked when a connection attempt fails
  chatController.onConnectFailure = function () {
    chatMain.output_txt.text +=  "Connection attempt failed." + "\n";
  };
   
  // Invoked when a connection attempt succeeds
  chatController.onConnectSuccess = function () {
    chatMain.output_txt.text +=  "Connection established." + "\n";
  };
   
  // Invoked when the server drops the connection
  chatController.onServerKillConnect = function () {
    chatMain.output_txt.text +=  "Connection terminated by server." + "\n";
  };
   
  // Invoked when Flash closes the connection
  chatController.onClientKillConnect = function () {
    chatMain.output_txt.text +=  "Connection closed." + "\n";
  };
   
  // Add a listener to capture Enter key presses
  chatController.onKeyDown = function () {
    // If the Enter key is pressed while the cursor is in the send field...
    if (Key.getCode() =  = Key.ENTER
        && eval(Selection.getFocus()) =  = chatMain.send_txt) {
      // ...send the contents of the send field in a <MESSAGE> tag
      chatController.send("<MESSAGE>" + chatMain.send_txt.text + "</MESSAGE>");
   
      // Then clear the input field
      chatMain.send_txt.text = "";
    }
  };
  // Register the listener
  Key.addListener(chatController);
}

See Also

loadVariables( ), the LoadVars class, the XML class


Table of Contents