More Books
Flash Communication Server
Flash Communication Server
Table of Contents
Copyright
About the Authors
Brian Lesser
Giacomo
Joey Lott
Robert Reinhardt
Justin Watkins
Foreword
Preface
What Does FlashCom Offer?
What's in This Book?
How to Use This Book
Audience
ActionScript 1.0 Versus ActionScript 2.0
Server-Side ActionScript
The flash-communications.net Site
Director, Breeze, and Other Options
Flash Video Options
Licensing and Hosting Options
Conventions Used in This Book
Voice
Using Code Examples
Safari Enabled
Comments and Questions
Acknowledgments
Part I:  FlashCom Foundation
Chapter 1.  Introducing the Flash Communication Server
Section 1.1.  Clients and Servers
Section 1.2.  Creating an Application
Section 1.3.  Real-Time Messaging Protocol
Section 1.4.  The Communication Classes
Section 1.5.  Communicating with Application Servers, Databases, and Directory Servers
Section 1.6.  Firewalls and Security
Section 1.7.  Getting Started
Section 1.8.  Hello Video!
Section 1.9.  Conclusion
Chapter 2.  Communication Components
Section 2.1.  Overview of Communication Components
Section 2.2.  Summary of Communication Components
Section 2.3.  Creating an Application that Monitorsa Connection
Section 2.4.  Building a Simple Chat Room
Section 2.5.  Adding Audio and Video to the Chat Room
Section 2.6.  Forgoing the SimpleConnect Component
Section 2.7.  Conclusion
Chapter 3.  Managing Connections
Section 3.1.  Making a Connection
Section 3.2.  Managing a Connection
Section 3.3.  Reusing a NetConnection Object
Section 3.4.  Multiple Simultaneous NetConnection Objects
Section 3.5.  Testing and Debugging Network Connections
Section 3.6.  Subclassing the NetConnection Class
Section 3.7.  Communication Components Without SimpleConnect
Section 3.8.  Conclusion
Chapter 4.  Applications, Instances, and Server-Side ActionScript
Section 4.1.  Scripting Application Instances
Section 4.2.  Differences Between Flash ActionScript and Server-Side ActionScript
Section 4.3.  The Life of an Application Instance
Section 4.4.  Running a Simple Hello World Test Script
Section 4.5.  A More Realistic Example
Section 4.6.  Instance-to-Instance Communications
Section 4.7.  Script Filenames and Locations in Detail
Section 4.8.  Testing and Debugging Server-SideScript Files
Section 4.9.  Designing Communication Applications
Section 4.10.  Conclusion
Part II:  Audio, Video, and Data Streams
Chapter 5.  Managing Streams
Section 5.1.  A Simple Publisher/Subscriber Example
Section 5.2.  Stream Names
Section 5.3.  Publishing Streams in Detail
Section 5.4.  Playing Streams in Detail
Section 5.5.  The Stream Class
Section 5.6.  Publishing and Playing ActionScript Data
Section 5.7.  Creating Synchronized Presentations
Section 5.8.  The NetStream and Stream Information Objects
Section 5.9.  Stream Enhancements and Limitations
Section 5.10.  Conclusion
Chapter 6.  Microphone and Camera
Section 6.1.  Working with Microphone/Audio Input
Section 6.2.  Working with Camera Input
Section 6.3.  Building a Message-Taking Application
Section 6.4.  Building a Surveillance Application
Section 6.5.  Conclusion
Chapter 7.  Media Preparation and Delivery
Section 7.1.  Audio and Video Compression
Section 7.2.  Converting Prerecorded Materialto FLV Format
Section 7.3.  Using Flash Pro's Media Components
Section 7.4.  Enabling Multiple Bit Rate FLVsWithin an Application
Section 7.5.  Streaming MP3 Audio
Section 7.6.  Conclusion
Part III:  Remote Connectivity and Communication
Chapter 8.  Shared Objects
Section 8.1.  Objects and Shared Objects
Section 8.2.  Getting a Shared Object in Flash
Section 8.3.  Updates and Frame Rates
Section 8.4.  Scripting Shared Objects on the Server
Section 8.5.  Temporary and Persistent Shared Objects
Section 8.6.  Proxied Shared Objects
Section 8.7.  Shared Objects and Custom Classes
Section 8.8.  Avoiding Collisions
Section 8.9.  Optimizing Shared Object Performance
Section 8.10.  Broadcasting Remote Method Callswith send( )
Section 8.11.  A Simple Video and Text Chat Application
Section 8.12.  Conclusion
Chapter 9.  Remote Methods
Section 9.1.  Why Use Calls?
Section 9.2.  The send( ) and call( ) Methods
Section 9.3.  Client-to-Server Calls
Section 9.4.  Server-to-Client Calls
Section 9.5.  Server-to-Server Calls
Section 9.6.  A Simple Lobby/Rooms Application
Section 9.7.  Debugging Calls
Section 9.8.  Advanced Topics
Section 9.9.  Conclusion
Chapter 10.  Server Management API
Section 10.1.  Connecting to the Admin Service
Section 10.2.  Using the Server Management API
Section 10.3.  Server Management API Uses
Section 10.4.  Conclusion
Chapter 11.  Flash Remoting
Section 11.1.  The Remoting Gateway
Section 11.2.  Remoting Basics
Section 11.3.  Role of Remoting in FlashCom Applications
Section 11.4.  Securing Access
Section 11.5.  Conclusion
Chapter 12.  ColdFusion MX and FlashCom
Section 12.1.  Understanding ColdFusion MXand Flash Remoting
Section 12.2.  Using Flash Remoting to Log Events
Section 12.3.  Getting a List of Streams
Section 12.4.  Using ColdFusion and FTP to Mirror Streams
Section 12.5.  Conclusion
Part IV:  Design and Deployment
Chapter 13.  Building Communication Components
Section 13.1.  Source Files
Section 13.2.  People Lists
Section 13.3.  A Simple People List
Section 13.4.  Listenable Shared Objects
Section 13.5.  Status and People List
Section 13.6.  Text Chat
Section 13.7.  Shared Text
Section 13.8.  Video Conference and Video Window
Section 13.9.  PeopleGrid
Section 13.10.  Summary
Section 13.11.  Conclusion
Chapter 14.  Understanding the Macromedia Component Framework
Section 14.1.  The Component Framework
Section 14.2.  Under the Hood of the Chat Component
Section 14.3.  Creating a Simple Component from Scratch: SharedTextInput
Section 14.4.  Creating a Container Component: SharedAddressForm
Section 14.5.  Creating an Authenticating Component
Section 14.6.  Integrating Components with Your Existing Applications
Section 14.7.  Understanding the Framework
Section 14.8.  Conclusion
Chapter 15.  Application Design Patterns and Best Practices
Section 15.1.  Shared Object Management
Section 15.2.  Moving Code to the Server
Section 15.3.  Building Façades on the Server
Section 15.4.  Server-Side Client Queues
Section 15.5.  A Framework for Recording and Playing Back Componentized Applications
Section 15.6.  Components and Component Frameworks
Section 15.7.  Conclusion
Chapter 16.  Building Scalable Applications
Section 16.1.  Coordinating Instances
Section 16.2.  Scalability and Load Balancing
Section 16.3.  Conclusion
Chapter 17.  Network Performance, Latency,and Concurrency
Section 17.1.  Latency
Section 17.2.  Bandwidth
Section 17.3.  Concurrency
Section 17.4.  Conclusion
Chapter 18.  Securing Applications
Section 18.1.  The Three A's: Authentication, Authorization, and Accounting
Section 18.2.  Authentication
Section 18.3.  Authorization
Section 18.4.  Accounting
Section 18.5.  Suggestions and References
Section 18.6.  Conclusion
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
R
S
T
U
V
W

1.4. The Communication Classes

While RTMP conveniently manages the flow of multiple streams of data across a network, the real power of Flash and FlashCom for developers is realized in the high-level classes that make connecting to the server, sharing information, and streaming audio and video so easy and flexible. I'll briefly review the major classes, which will be explored in more detail and used in examples throughout the remainder of the book.

1.4.1. Connecting to the Server

The NetConnection class connects a client to an application instance on a server. In the simplest case, you can create a connection by invoking NetConnection.connect( ) with the URI of the remote application:

nc = new NetConnection(  );
nc.connect("rtmp://echo.ryerson.ca/campusCameras/connector");

To determine if the connection was established successfully, define an onStatus( ) method on the NetConnection object before invoking connect( ):

nc = new NetConnection(  );
nc.onStatus = function (info) {
  trace("The connection code is: " + info.code);
};
nc.connect("rtmp://echo.ryerson.ca/campusCameras/connector");

In this example, the RTMP address includes the host (echo.ryerson.ca), the application name (campusCameras), and the instance name (connector). If you've ever developed network applications using other application programming interfaces, you'll likely agree that creating a network connection between Flash and FlashCom is ridiculously easy. Chapter 3 goes into greater detail on the NetConnection class and how to use NetConnection objects.

1.4.2. Streaming Audio, Video, and ActionScript Data

Once you establish a connection using a NetConnection object in the client, you can use it to send or receive a stream containing audio and/or video. Suppose you know that a recorded Flash video file named Ryerson_High_Speed.flv is available in the instance's public directory. You can attach the video stream to a video object, here named videoArea, using Video.attachVideo( ) and play it using NetStream.play( ). The NetStream object, in_ns, is created by passing the NetConnection object, nc, from the preceding example to the NetStream( ) constructor function:

in_ns = new NetStream(nc);
videoArea.attachVideo(in_ns);
in_ns.play("public/Ryerson_High_Speed");

In this case, the video appears in a video object that was placed on the Stage during authoring and given the instance name videoArea; the audio within the video stream is heard automatically. Note that the .flv extension is not included in the stream URI passed into the play( ) method.

Publishing a stream in a Flash movie is also easy. Here, we create a new NetStream object, out_ns, and attach the audio and video streams from the user's microphone and camera before publishing the stream using NetStream.publish( ):

out_ns = new NetStream(nc);
out_ns.attachAudio(Microphone.get(  ));
out_ns.attachVideo(Camera.get(  ));
out_ns.publish(userName);   // Name the stream after the user's name.

The Camera class can get a video stream from a web camera or other video source, and the Microphone class can get an audio stream from a microphone or other source.

You can create multiple streams (NetStream objects) for a single NetConnection, as shown in Figure 1-3. Each stream can publish or play a stream to or from the server, but data within a stream travels in only one direction. If each user must publish a single stream, it is easiest to name the stream after his unique username or unique ID number.

Figure 1-3. A client publishing a stream and receiving two streams over one NetConnection


On the server, the Stream class can be used to create playlists of streams and even to play and publish streams across multiple servers. A playlist defines a sequence of streams to be played one after the other. The server buffers them so they play seamlessly without interruption; when one stream ends, another begins. Chapter 5 covers the NetStream and Stream classes in depth.

1.4.3. Camera, Microphone, and Video

The Camera and Microphone classes, covered in depth in Chapter 6, provide access to video and audio sources (typically cameras and microphones) on the client system. Multiple cameras and microphones can be accessed by the same Flash movie. Only one video and audio stream can be published or played within a single NetStream; however, there can be multiple NetStreams within a single NetConnection, as shown in Figure 1-4. The Flash Player is responsible for encoding all audio and video data. Video encoding from each video source is currently limited to constant bit rate encoding at a single resolution. The Camera and Microphone classes can be used to control the amount of audio and video data being sent to the server and can be dynamically adjusted to match the bandwidth limitations of the clients connected to an application. No real-time hardware encoding options are currently available, though that may have changed by the time you read this. Some video cards can present different resolution video streams from the same input as separate video sources so that multiple NetStream objects carrying different resolution video from the same source can be published simultaneously. Otherwise, the only way to provide different streams matched to the bandwidth of each client is to use multiple video sources.

Figure 1-4. Attaching audio and video sources to a published stream and attaching a playing stream to an embedded Video object to view incoming video


The Camera class provides a convenient way to change the resolution, frame rate, and quality settings for each video source. The Microphone class allows setting the sampling rate, gain, and silence level, among others. A Video object is used to display video within a Flash movie and can be dynamically resized and moved as video is played. See Chapter 6 for working examples.

1.4.4. Sharing Data in Real Time

Real-time applications often require data to be shared among or transmitted between multiple movies. The SharedObject class is familiar to many Flash programmers as a way to create a kind of supercookie; a local shared object (LSO) can store ActionScript data on the client between sessions. Flash communication applications can use remote shared objects (RSOs) to share information in real time between movies running on different clients. If a movie updates a property of a remote shared object, the same property is updated in every other movie connected to it. When a shared object changes, each client is notified of the changes. Shared objects can be used to:

  • Notify all the movies connected to a video conference application of the name of every available live stream

  • Update the position of elements in a game

  • Hold the position, shape, and color information of each graphical element in a shared whiteboard

  • Hold the data for each form element in a shared form

In object-oriented programming (OOP), the data within all the objects in an application defines the current state of the application.

Shared objects provide a convenient mechanism to hold the state of a communication application distributed across multiple clients and servers.


Remote shared objects can be temporary or persistent. Temporary shared objects last only while they are being used. Persistent shared objects are saved on the server when they are not in use, allowing clients to pick up where they left off as soon as they reconnect to the server. Proxied shared objects are a mechanism for making shared objects available across multiple application instances; one application instance always owns the shared object but others can create a network connection to the master instance and create proxies (essentially an alias) of the shared object. That way, clients connected to any instance can connect to the same shared object. The feature is often important for creating large scale applications.

The code to work with shared objects on the client is a little different from that required on the server. Working with shared objects is also a little more complicated than working with streams or managing network connections. You need to do four basic things when working with shared objects:

  1. Get a remote shared object using SharedObject.getRemote( ).

  2. Customize the shared object so your program can respond to changes made to the shared object by each movie or by the server.

  3. Connect to the shared object.

  4. Once connected, update the shared object's properties as necessary.

Chapter 8 provides complete coverage of using shared objects, but let's have a quick look at what some client-side code looks like. On the client, the SharedObject.getRemote( ) method returns a remote shared object. However, the shared object usually needs to be set up with an onSync( ) method and then connected using a NetConnection object before it can be used. Here we get a shared object named users to which each movie will connect. Then, an onSync( ) method is defined that, for demonstration purposes, displays information about changes made to the shared object as soon as they occur. Then the shared object is connected to the server:

users_so = SharedObject.getRemote("users", nc.uri);
users_so.onSync = function (infoList) {
  for (var i in infoList) {
    var info = infoList[i];
    switch (info.code) {
      case "change":
        var id = info.name;
        trace("User connected with id: " + id);
        trace("and name: " + users_so.data[id]);
        break;
      case "delete":
        var id = info.name;
        trace("User disconnected with id: " + id);
        break;
    }
  }
};
users_so.connect(nc);

The onSync( ) method is often the most interesting part of shared object coding. When the local copy of the shared object is synchronized with the server and whenever any slots (properties) in the shared object change, the onSync( ) method is invoked automatically. The onSync( ) method is passed an array of information objects. Each object contains information about the shared object or about what has happened to a slot (property) in the shared object. Chapter 8 describes shared objects and the onSync( ) method in detail. Each information object has a code property, which describes what happened ("clear" if every slot is deleted, "change" if a slot is added or updated remotely, or "delete" if a slot is deleted). The name of the slot that has been updated or deleted is always found in the information object's name property. To add or update data to a shared object slot within Flash, use the data property of the shared object:

users_so.data["guest_4"] = "brian";

Likewise, you can retrieve the value in a slot using the data property:

trace("The user's name is: " + users_so.data["guest_4"]);

1.4.5. Client and Application Objects

Whenever a client connects to an application instance on the server, a Client object is created on the server side to represent the remote client. The Client object can be used by server-side scripts to send and receive data messages to and from each individual remote Flash client. Every application instance also has a single application object that provides a convenient way to manage the instance's life cycle. The application is a singleton instance of the server-side Application class.

Scripting Client objects and the application object is covered in Chapter 4. The Client and application objects, in concert with the ability to query web application servers, provide the core features needed to authenticate clients as they connect. Authentication is covered in detail in Chapter 18.

1.4.6. Remote Methods

In a typical application, an individual client may need to ask the server to perform some action on its behalf. For example, it may need to ask the server for the length of a recorded stream before playing it. The server may also have to ask the client to do something. For example, the server may need to have the client use a unique string provided by the server to name the streams the client will publish. Remote method calls are a way that the client and server can invoke methods on each other.

An application instance can invoke a method on a client using the Client.call( ) method. A client can invoke a method on an application instance using the NetConnection.call( ) method. For example, a server-side script can invoke a method on an individual client in order to let the client know its unique ID number:

client.call("setID", null, id);

If a client method named setID( ) is invoked using Client.call( ) from the server, the method must be defined on the client's NetConnection object or nothing will happen. For example, the client-side script might look like this:

nc = new NetConnection(  );
nc.setID = function (id) {
  myID = id;
};

Conversely, the client can call a method on the server using a NetConnection object:

nc.call("getStreamLength", streamInfoResponder, streamName);

For a result to be returned by the remote method, the second parameter passed to NetConnection.call( ) must be a object with an onResult( ) method.

FlashCom also supports mechanisms to send a remote method request to multiple clients at the same time. Clients connected to the same shared object or playing the same stream can all receive a remote method call at the same time. For example, a popular way to update a text chat area is to use the send( ) method of a shared object to send a text message to every client:

chat_so.send("showMessage", "Welcome to the chat.");

In this case, a showMessage( ) method must be defined on the shared object or nothing will happen:

chat_so.showMessage = function (msg) {
  chatTextArea.text += msg + '\n';
  chatTextArea.vPosition = chatTextArea.maxVPosition;
};

Chapter 9 describes calling and defining remote methods in detail.