support for a persistent client/server TCP/IP connection | | Constructornew 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: -
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. Table 18-29. Flash-compatible socket servers 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 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. | 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 |