-Requirements    
Prerequisite knowledge    Required products    
You should be familiar with Flash Professional 8 and ActionScript 2.0. Some knowledge of server-side ActionScript with Flash Media Server 2 is also beneficial.
Flash Media Server 2 (Download trial)
 
User level    
Intermediate
   
Additional Requirements

Tutorials and sample files:

Macromedia Flash Media Server 2 makes it possible for you to build rich Internet applications whose functionalities go far beyond simply streaming Flash video. Maybe you have come across multiplayer games that are powered by FMS 2 or chatted away using a live webcam and microphone feed—all through a Flash front end.
 
What FMS 2 adds to these applications, apart from the obvious audio and video feeds, is the ability to invoke remote methods (often referred to as remote method invocation or RMI) on the server itself or even on another client.
 
As an already experienced Flash developer, you will probably realize that this opens the door for a multitude of features and collaborative applications that would not be possible outside a client-server architecture.
 
This article walks you through the different RMI mechanisms that are available through Flash Media Server 2 and provide you with some guidance on when to use which one.

Overview of Remote Methods

Flash Media Server provides you with several different ways to invoke functions in remote locations, such as your server, other servers, and connected clients. To pick the method that solves your particular task most efficiently, you should familiarize yourself with these mechanisms—some of which are a bit like a one-way street and do not allow you to receive any return values, whereas others offer asynchronous returns.
 
Using SharedObject.send
The SharedObject.send method works in conjunction with a remote shared object and allows you to invoke a method that is defined on the shared object. Anyone connected to the shared object is able to receive the .send request.
It works a bit like a radio station: you know that everyone who is tuned in to your station (connected to the remote shared object) will be able to hear you (when you broadcast using .send).
Therefore SharedObject.send is ideally suited for applications such as text chats, where you can send your message and feel confident that everyone who wants to see it can do so. Moreover, you do not care who or how many people are "listening in," nor do you need confirmation that they have received your message.
It should also be noted that you, as the "broadcaster," will receive your own remote method callback when you use SharedObject.send. This is one major difference between SharedObject.send and the next method on our list.
 
Using NetStream.send/Stream.send
 
The NetStream.send method (and its server-side sibling, Stream.send) are very similar to the SharedObject.send method. They too work like the radio station previously described. The main difference is that the .send method is attached to the NetStream object and is not a shared object.
To be able to broadcast messages over a NetStream object using .send, you must be the publisher of the stream. Subscribers of a particular NetStream object are not able to use the .send method. Moreover, the originator of the message does not receive his or her own request back.
One very powerful feature of the NetStream.send method is the fact that you can record the event. This means that when Flash Media Server records any .send requests issued during the lifetime of a NetStream object, it stores those requests as part of the recording at the exact time the request was sent. Upon playback of the recorded stream, FMS invokes the .send requests again just as they were during actual recording. This opens the door for powerful applications that synchronize events—for example, of a live webcast upon playback some time later.
 
Right now, the only way to record a live Flash video stream is by using Flash Media Server. In this context, I should note that the .send calls are invoked upon playback even if this recorded FLV file is later delivered using progressive download. Pretty neat!
 
Using NetConnection.call
 
While the .send method of both the shared object and NetStream object offer a mechanism to broadcast a request to a whole group of users, NetConnection.call is a little more personal because it targets just one party—which in our case is the server. The NetConnection.call method is a client's channel to the server, allowing you to invoke a server-side method that is also able to send you an optional return value.
For this reason, NetConnection.call is often used to inform the server of a client's state ("Hey server, I'm going to idle for a bit") or to request information that only the server would be able to supply ("Yo server, could you tell me how many other users are connected to you right now?").
 
Using Client.call
 
If you have grasped NetConnection.call, then you won't have many difficulties understanding the Client.call method. It's basically NetConnection.call in reverse.
Client.call
is the server's way of invoking a method on a particular client. Just like NetConnection.call, it can return an optional response back to the server ("Hey client, I am about to kick you out of this chat—do you mind?").
 
Also Using SharedObject.onSync
 
If you are already experienced in developing applications for Flash Media Server, then you know that there is a fourth method that is similar to SharedObject.send, which allows you to distribute information to everyone connected to the shared object. The SharedObject.onSync method is invoked whenever a value of one of the data slots of the shared object changes.
While this is one of the most powerful features (in my humble opinion) of Flash Media Server, I do not count it as a way to invoke remote methods. Instead, it acts more like a storage box for data that automatically synchronizes with all connected clients. I will not cover the SharedObject.onSync method in this article, but I recommend that you see the Flash Media Server documentation if you want to find out more about it.

A Simple Chat Application

One of the most common (or should I say most obvious) applications that you can build almost exclusively on top of SharedObject.send is a simple chat application. Let's take a closer look at one (see Figure 1). Instead of recreating the complete application for this example, I will just zoom in on the important parts.
 
Simple chat application
Figure 1. Simple chat application
 
Note: This example assumes that you have installed Flash Media Server on your local machine and that it is running. You also need to create a new application folder called simplechat and copy the file main.asc from the sample download's simplechat folder into it (see Figure 2). For more information about setting up applications on Flash Media Server, see the Flash Media Server documentation.
 
Copying main.asc into the simplechat application folder in FMS 2
Figure 2. Copying main.asc into the simplechat application folder in FMS 2

 

Open simplechat.fla as well as SimpleChat.as in the Flash authoring environment. SimpleChat.as is a class file linked to the
simplechat
movie clip on the Stage. Let's examine the code in more detail and, in particular, the usage of
SharedObject.send
.
If you scroll down to line 75, you will find the
connectSO
method, which sets up the remote shared object once NetConnection has been established to the server.
Line 102 sets up a method called chatMsg on the shared object:
_chatSO.chatMsg = function ( msg, fromwho )
This method is the one that is being called with SharedObject.send when a user submits a chat message and it accepts two parameters, msg and fromwho. The msg parameter contains the actual chat message, while fromwho indicates who sent the message.
The code that follows simply formats this text and pushes it into a text area on the Stage:
var chatmessage = "<FONT FACE='Verdana' SIZE='11'><b>" + fromwho + "</b>: " + msg + "</FONT>"; history_ta.text += chatmessage; // scroll down history_ta.vPosition = history_ta.maxVPosition; history_ta.redraw();
Line 130 contains the actual SharedObject.send statement which, when called, invokes _chatSO.chatMsg on all connected clients passing it the msg and fromwho parameters:
_chatSO.send("chatMsg", msg, fromwho);
Feel free to modify this application further—maybe by adding additional parameters to the
_chatSO.chatMsg
method that will allow you to target a specific user.
One thing to remember is this: SharedObject.send is ideally suited to inform all connected users easily about a specific event. The server too can invoke SharedObject.send; the request does not have to originate from a client.

Record and Play Back Events

The
NetStream.send
method and its server-side equivalent,
Stream.send
, behave very similarly to
SharedObject.send
. I have therefore decided not to build a similar example to the previous chat application (which would have involved setting up a stream, subscribing to it, and calling
.send
on it). Instead, I show you how
NetStream.send
events can be recorded and played back at a later time, preserving the events as part of the recorded stream.
Open the file recordevents.fla in Flash and select frame 1 of the Actions layer. Open the Actions panel.
Just as in the previous sample application, you first need to establish a NetConnection call to Flash Media Server. In this case, you must first create an application named recordevents in your server's applications directory. No server-side code is necessary for this application to run.
Once you have established a NetConnection call, a NetStream object is created ready for use (lines 25 to 29). While a user drags the bird around the Stage, the bird's position is constantly being saved into a NetStream object named bird which is being recorded on the server (see Figure 3).
Moving the bird around the stage and recording it on the server
Figure 3. Moving the bird around the stage and recording it on the server
Lines 40 to 44 take care of the data being sent to the NetStream object every time the onMouseMove event is invoked:
this.onMouseMove = function() { // use ns.send to record the bird's x and y position ns.send("storePosition", this._x, this._y); }
The name
storePosition
is a method name I have chosen. You could have named this method any way you like. The only thing you need to be aware of is keeping the method name consistent with the method name on the receiving end.
In my example here, the so-called receiving end is equivalent with the playback of the recorded stream. In other cases, however, the receiving end may be another user who subscribed to a live stream that you are broadcasting.
Note that in this example, you do not send any audio or video over your stream; all you record is data.
"Big deal," I hear you say, "This is nothing new!" All you're doing is recording a stream. You are right, of course, and nothing much happens at all until the user releases the mouse. At that moment your publishing stream stops (line 63):
ns.publish(false);
And playback of the same (but now recorded) stream starts (line 64):
ns.play("bird");
The main logic of this application follows (lines 66–71):
ns.storePosition = function(xpos, ypos) { trace("position: " + arguments); bird._x = xpos; bird._y = ypos; }
This method grabs the recorded data that you previously sent over the NetStream object (remember the naming consistency of
storePosition
that I mentioned?) and repositions the
bird
movie clip in exactly the same way that we did upon recording, effectively replaying its exact movements.
It does not take much imagination to see the potential benefits of this sort of setup. Even Macromedia Breeze uses
NetStream.send
for some of its in-built synchronization capabilities, such as replaying chat conversations alongside other content.
I will not cover Stream.send in any more detail here because it is, effectively, the server-side equivalent of NetStream.send and behaves in pretty much the same way.

Combined NetConnection.call and Client.call Example

In this last section, you will learn how to invoke a method on the server using
NetConnection.call
and how to let the server call a method on a specific client using
Client.call
. Both methods have their own set of use cases, which should become obvious once you see these mechanisms in action.
Imagine a situation where a client needs to request the number of currently connected users from the server. (The server can always get this figure using
application.clients.length
.) One way of storing this number may be in a remote shared object that the server updates upon every connect or disconnect.
But sometimes it's easier and simpler to make this information available on request without having to take care of maintaining the right number. This is what you will do in the next example, which uses your previous simplechat application and some additional new methods.
 

Note: This example assumes that you have installed Flash Media Server on your local machine and that it is running. You also need to create a new application folder called simplechat_call and copy the file main.asc from the sample download's simplechat_call folder into it (see Figure 4).

 

Copying main.asc into the simplechat_call application folder in FMS 2
Figure 4. Copying main.asc into the simplechat_call application folder in FMS 2
 
Invoking a Server-Side Method Using NetConnection.call
Open simplechat_call.fla, SimpleChat_call.as, and main.asc in the Flash authoring environment. SimpleChat_call.as is a class file which is linked to the
simplechat_call
movie clip on the Stage.
You may notice that this class is almost identical to the previous simplechat application but that a few new methods have been added. Let's look at these additions more closely.
The first new piece of code is on line 75:
_nc.receiveUsercount = function (count) { [...] }
This code defines a method
receiveUsercount
on the existing NetConnection object. Don't worry if this doesn't make much sense just yet. Just know that when the server uses
Client.call
, the server invokes the method; this is the server's way of invoking a remote method on a client. You'll find out more about this in a few moments.
You may also notice a new pushbutton instance on the Stage with the label get usercount. When clicked, this button invokes the onUserCount method defined at the bottom of your class file:
// method to request user count from server private function onUserCount() { trace("client requests usercount from server"); _nc.call("userCount", null); }
This method, in turn, invokes a remote method on the server using NetConnection.call:
_nc.call("userCount", null);
The parameter
null
tells you that no return value is expected. I decided against a return value in order to demonstrate better the
Client.call
call on the server side, which is being invoked in response to our NetConnection call.
For the sake of this example, it's sufficient if you know that both
NetConnection.call
and
Client.call
can optionally and asynchronously return a value to the caller. For more details about this, see the Flash Media Server documentation on
NetConnection.call
as well as
Client.call
.
Invoking a Client-Side Method Using Client.call
So what's next? Correct: the server-side code. Have a look at main.asc and scroll to line 44:
Client.prototype.userCount = function() { // get the number of connected users var count = application.clients.length; // 'this' refers to this client, the client who is invoking Client.prototype.userCount; this.call("receiveUsercount", null, count); }
Here you define a new method, called userCount, on the client's prototype, which allows any connected client to invoke this method using the following:
_nc.call("userCount", null);
Once invoked, the server establishes the current user count by saving
application.clients.length
into a variable count and then invoking the
receiveUsercount
method on the very client that just invoked the server-side
userCount
method. This closes the loop of client-to-server-to-client and informs the client of the current number of connected users.
Remember the client-side method _nc.receiveUsercount on line 75? It should now be clear why it exists: It is the receiveUsercount method that the server invokes to pass the usercount variable to the client.
 
Where to Go from Here
 
I covered a lot of ground in this article and you may be feeling a little out of breath. Don't worry; the topics I covered will give you the basic skills that you need to build powerful multiuser applications. You should feel confident when deciding upon the type of remote method invocation that is best suited for your particular application.
You can find a list of resources covering Flash Media Server on my FlashComGuru site.
For questions, comments, or suggestions regarding this article, feel free to e-mail me or visit my forum, where you will also find a thread dedicated to this article.