Section 9.4. Server-to-Client Calls

9.4. Server-to-Client Calls

We've seen how to invoke a server-side function from a client. Let's look at the reverse scenario in which server-side scripts ask a particular client movie to perform some operation using Client.call( ) .

The server-side syntax is very similar to the client-side NetConnection.call( ) method discussed earlier. Here is the server-side code:

 my_client.call(clientMethodName, resultObject  null, [, p1, ...p   n   ]); 

where my_client is the instance name of the Client object you want to invoke the method on.

The first parameter of call( ) is clientMethodName , a string (such as "test", or "setUserID") that specifies the name of the method to invoke on the client side.

Almost any valid identifier name can be used as a method name. Avoid strings with spaces and don't use reserved words and methods such as call , close , connect , isConnected , onStatus , and uri .

The second parameter can be either null or a result object.

The optional parameters p1, ...p n are passed as parameters to the method on the client. All the parameter types discussed earlier under "Other Parameter Types" can be passed to this call as well.

The server-side Client.call( ) method returns a Boolean ( TRue if the call was sent, false if it failed immediately). In order for the call to work, you will need to define a method on the client side that matches the name of your first parameter ( clientMethodName ) and attach it to the client-side NetConnection object.

Let's see some examples.

9.4.1. Simple call( ) Example: "Client, Here's Your ID"

Since server-side code executes in a single thread, a typical task performed on the server is assigning a unique ID to each connecting client. Here's some code, which can be placed in a main.asc file, that does the trick:

 application.onAppStart = function (  ) {   this.nextID = 0; }; application.onConnect = function (clientObj) {   clientObj.userID = this.nextID++;   trace("client " + clientObj.userID + " is connecting");   this.acceptConnection(clientObj);   clientObj.call("setUserID", null, clientObj.userID); }; application.onDisconnect = function (clientObj) {   trace("client " + clientObj.userID + " is leaving"); }; 

The code resets the counter ( nextID ) every time the application starts and increments it every time a user connects. Right after accepting the client connection, we can start making calls to the client safely, as we do in this line:

 clientObj.call("setUserID", null, clientObj.userID); 

We need to define a method in the client and attach it to the NetConnection object, in order for the method to be invoked by the server. Here is the client-side code:

 my_nc.setUserID = function (id) {   _root.myID = id;   // ...other code to set up the UI. }; 

where my_nc is the name of the NetConnection object instance on the client side. In this example, we store the unique ID as a property of _root .

9.4.2. Contacting Clients

In a common scenario, the server wants to tell something to all (or a subset of) the clients connected to the application. You can do this in several ways:

  • Use NetStream.send( ) as described in Chapter 5.

  • Use SharedObject.send( ) as described in Chapter 8.

  • Have all the clients you want to notify connect to a shared object and set a property on that shared object using the SharedObject.setProperty( ) method. This will trigger an onSync( ) on all clients, as also discussed in Chapter 8.

  • Loop through the application.clients array and make a server-to-client call to all the clients you want to notify, as discussed next .

9.4.2.1 Looping through the clients array

Here's a little server-side code snippet that loops through the application.clients array:

 for (var i = 0; i < application.clients.length; i++) {   var c = application.clients[i];   if (c.role == "viewer") {     c.call("showViewerUI", null);   } } 

The code loops through all the clients connected to the application and saves a reference to each client in the c variable. The code checks whether the role property of the client (attached to the client instance somewhere else in your script; not shown) is equal to "viewer"; if so, the code invokes showViewerUI( ) on the selected client.

9.4.3. Using a Result Object: "Client, Are You OK?"

Just as a client-to-server NetConnection.call( ) method can return a value to the client, the server-to-client Client.call( ) method can return a value to the server. The syntax is identical, so let's dive down into an example.

Sometimes you want to make a round-trip call to a client to make sure it's still alive. Here's the server-side code to check whether a client is alive :

 // Define a class that just stores the client ID. AreYouOkResultHandler = function (clientID) {   this.clientID = clientID; }; // Handle the result of calling   areYouOk( )   . AreYouOkResultHandler.onResult = function (val) {   trace("Client " + this.clientID + " returned " + val); }; application.pingClient = function (clientObj, clientID) {   // Invoke a message on the client.   clientObj.call("areYouOk", new AreYouOkResultHandler(clientID)); }; 

On the client side, we can define the simple areYouOk( ) method and attach it to the NetConnection object, like this:

 my_nc.areYouOk = function (  ) {   return true; }; 

Using a return object in a server-to-client call is very rare, as one would usually make use of shared objects to maintain information about clients. It's more common in server-to-server calls, which we will discuss in the next section.

How to Remember the Syntax

Most developers get confused at first by the asymmetry of making calls and attaching methods on the NetConnection and the Client objects when using remote methods in FlashCom. Here's a little reminder.

For client-to-server calls, the NetConnection is the only way out of the client, so the call should start there. Invoke NetConnection.call( ) from the client-side Flash movie, specifying the name of the handler to be invoked on the server:

 my_nc.call("serverHandlerName"); 

and from the server's point of view, every connection to the outside world is a different client movie, so define the SSAS handler as a method of the server-side Client object:

 clientObj.serverHandlerName = function (  ) {/* Code goes here */}; 

Conversely, for server-to-client calls, the server connects to many client movies, so calling a method on a particular client is done by invoking Client.call( ) from SSAS:

 clientObj.call("clientHandlerName"); 

and from the client point of view, the only way in from the server is the NetConnection object, so it's logical to define the client-side method on NetConnection :

 my_nc.clientHandlerName = function (  ) { /* Code goes here */ }; 

If you think about it, it's logical. Just remember that the Client object is used exclusively on the serverit represents the client making the connection.




Programming Flash Communication Server
Programming Flash Communication Server
ISBN: 0596005040
EAN: 2147483647
Year: 2003
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net