XMLSocket Class | Flash 5 |
support for a persistent client/server TCP/IP connection |
new XMLSocket()
Terminate an open connection to a server application.
Attempt to establish a new connection to a server application.
Send an XML object hierarchy to a server application as a string.
Executes when the server terminates the connection.
Executes when a connection attempt completes.
Executes when data is received but has not yet been parsed as XML.
Executes when data has been received and parsed into an XML object hierarchy.
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:
Once the connection closes, the server has no way of contacting Flash. Flash must always initiate communication with the server.
Each time Flash obtains information from the server, a new connection must be opened. The time and processor load involved in opening connections repeatedly prevents Flash from engaging in anything near real-time transactions with a server.
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:
Serve TCP/IP socket connections on a specific port greater than or equal to 1024
Transmit XML-formatted data in segments delimited by a zero byte (i.e., the ASCII null character)
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.
Name |
Description |
License |
Location |
---|---|---|---|
moockComm |
A light-weight reference implementation, written in Java |
Free |
|
aquaServer |
A light-weight reference implementation, written in Java |
Free |
|
Unity |
A full-featured rooms-based server written in Java |
Pay |
|
Fortress |
A mature, heavy-duty socket server |
Pay |
|
ElectroServer |
A full-featured, real-world tested socket server |
Pay |
An XMLSocket connection stays open until one of the following occurs:
The close( ) method of the XMLSocket object is called.
No more references to the XMLSocket object exist.
The server terminates the connection (this triggers an onClose( ) event).
The movie is unloaded or the Flash Player exits.
The XMLSocket class also provides four event handlers—onClose( ), onConnect( ), onData( ), and onXML( )—that allow us to monitor the status of an open connection.
|
For extensive information on XMLSocket development, see:
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:
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.
/* * 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.
// 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); }
loadVariables( ), the LoadVars class, the XML class