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

3.1. Making a Connection

NetConnection objects are created by calling the NetConnection( ) constructor function:

lobby_nc = new NetConnection(  );

In this example, the lobby_nc variable stores a NetConnection object, which can be used to attempt to connect to an application instance:

if (lobby_nc.connect("rtmp:/testLobby", userName, password)) {
  trace("Attempting connection...");
}
else {
  trace("Can't attempt connection. Is the URI correct?");
}

In this example, the URI rtmp:/testLobby is the address of an instance of an application named testLobby that resides on the server from which the movie was downloaded. The connect( ) method is always passed the URI of the application instance to which to connect, followed by any number of optional parameters. In this example, a username and password are supplied after the URI. The connect( ) method returns false if it detects a malformed URI; otherwise, it returns true, and Flash attempts to connect to the server.

Not all malformed URIs are caught by the connect( ) method. You must always make sure the protocol is either rtmp or rtmpt followed by a colon; otherwise, the connect( ) method may return TRue and then fail.


The URI can be an absolute URI that includes a hostname or a relative URI that does not. After the connect( ) method is called, the URI passed into it is available as the uri property of the NetConnection object.

3.1.1. Absolute URIs

An absolute URI is a string that includes protocol, host, optional port, application name, and optional instance name segments. The format of an absolute URI is:

rtmp[t]://host[:port]/applicationName[/instanceName]

The parts of the URI in square brackets are optional. An absolute URI contains all the information needed to identify an application instance to which to connect. The following sections describe all the parts of an absolute URI.

3.1.1.1 Protocol

The first part of an absolute URI is the protocol or scheme and must always be specified as rtmp, rtmpt, or rtmps, followed by :// for an absolute URI or :/ for a relative URI. RTMP is preferred because it is the native protocol for FlashCom communications. Adding the optional t in rtmpt indicates that HTTP tunneling is to be used. Tunneling is less efficient, because RTMP messages must be wrapped in HTTP headers, and the server must be constantly polled by the Flash movie. However, tunneling may successfully make connections through firewalls and proxy servers when RTMP access fails. Tunneling was first added to Flash Player 6.0.65.0 and FlashCom 1.5. When run in a browser, the Flash Player uses the browser to make the HTTP connections to the server that RTMPT relies on. Since the browser normally also supports SSL, Macromedia added the ability to use the SSL by specifying the rtmps protocol instead of rtmpt. When RTMPS is used, the Flash Player attempts to establish a tunneling connection over HTTPS to FlashCom. Even though FlashCom 1.5 does not support SSL, it is possible to take advantage of RTMPS using additional server software or specialized network hardware in order to have completely encrypted real-time communications between Flash movies and FlashCom. Configuring a system to accept SSL connections is briefly discussed in Chapter 18 and at:

http://www.macromedia.com/devnet/mx/flashcom/articles/firewalls_proxy04.html

If an SSL certificate is used from an authority the browser does not recognize, anyone connecting via RTMPS will be asked to accept or install the certificate before the connection can be completed. Currently, clicking Yes to accept the connection will not work. The certificate must be installed and the connection retried.


3.1.1.2 Host and port

An absolute URI always contains a hostname after the :// characters. Optionally, you can specify a port on the host by following the hostname with a colon and a port number. FlashCom's default port is 1935; however, it can be configured to accept connections on a different port or ports. If the rtmp protocol is specified and no port is given in the URI, the Flash movie attempts to connect to port 1935. If the connection attempt fails because the server cannot be reached, the Flash Player automatically attempts to connect to FlashCom on port 443. If that also fails, the Player attempts to connect to port 80. Finally, if an RTMP connection cannot be made on any of those three ports, the Player tries one last time to make a tunneling (RTMPT) connection on port 80. The sequence of ports and protocols is listed in Table 3-1.

Table 3-1. Port connection sequence

Sequence

Port

Protocol

1

1935

RTMP

2

443

RTMP

3

80

RTMP

4

80

RTMPT


The sequence in Table 3-1 is attempted only when the protocol in the URI is rtmp and no port is specified. If rtmpt is specified in the URI and no port is provided, the Flash movie attempts to connect to port 80. When rtmps is used, the default port is 443.

If FlashCom is configuredr to listen on a port other than 1935, 443, or 80, the port must be specified in the URI. For example, if the server is configured to use port 8080, the URI might look like this:

rtmp://host.domain.com:8080/conferenceRooms/room_23

Selecting another port is not recommended, however, because port 1935 was assigned to the Macromedia Flash Communication Server MX by the Internet Assigned Numbers Authority. A production configuration can also set up the server to listen on more than one port. Port information can be set using the Adaptor.xml configuration file's <HostPort> tag. An Adaptor.xml file is located inside each adaptor's directory inside the conf directory. On our machine with a default Windows installation, the default Adaptor.xml file is located here:

C:\Program Files\Macromedia\Flash Communication Server MX\conf\_defaultRoot_\Adaptor.xml

If a web server is not already running on port 443 or 80, the <HostPort> tag can include the port numbers 1935, 443, and 80. If no port number is supplied in the target URI and a remote firewall blocks access to the server on port 1935 but allows access via port 443, the second connection attempt will succeed. Port 443 is normally associated with encrypted communications over SSL. Neither FlashCom 1.5 nor the Flash Player provides direct SSL support.

For details on connecting to the FlashCom Admin Service application on port 1111, see Chapter 10. For an example application that uses port 1111, see Chapter 12.

3.1.1.3 Application name

The application name must be specified in the URI. On the server, the application name is the name of a subdirectory in the server's applications directory. Often, each application is a subdirectory in the Macromedia Flash Communication Server MX/applications directory. However, a server can have multiple virtual hosts, each with its own applications directory. Each virtual host is associated with a domain, which is in turn mapped to an applications directory. To determine the location of the applications directory for a virtual host, check the <AppsDir> tag in the Vhost.xml file. The default Vhost.xml is in the conf/defaultRoot/defaultVHost_ subdirectory of the directory in which FlashCom was installed. The applications directory itself is never part of the URI as the hostname maps to it.

3.1.1.4 Instance name

The instance name specifies which instance of an application to connect to. It does not have to be specified within a URI. If it is omitted, the default name _definst_ is used. These two URIs refer to the same instance:

rtmp://host.domain.com/conferenceRooms
rtmp://host.domain.com/conferenceRooms/_definst_

Application instance names can form a hierarchy. For example, a chat room application may provide many chat rooms for different courses in different university programs. To accommodate this situation, the format for instance names could follow a scheme in which the hierarchy helps to keep items organized, like this:

program/courseName/chatRoom

So some URIs might look like this:

rtmp://my.university.edu/chatRooms/science/phys325/room8
rtmp://my.university.edu/chatRooms/motionPicture/film001/room8
rtmp://my.university.edu/chatRooms/motionPicture/film021/room3
rtmp://my.university.edu/chatRooms/motionPicture/film021/room4

Each one of these URIs is an address of a separate instance of the chatRooms application even though two of them contain the name "room8". The instance name /chatRooms/motionPicture/film001/room8 is not the same as chatRooms/science/phys325/room8.

3.1.2. Relative URIs

If a .swf file is loaded into a browser from the same server that FlashCom is running on, you can use a relative URI in which the // characters and hostname are omitted. Here is the format for a relative URI:

rtmp[t]:[:port]/applicationName[/instanceName]

In the earlier rtmp:/testLobby example, the protocol is rtmp, the single slash indicates a relative URI, and testLobby is the application name. No application instance name is provided, so the _definst_ instance is assumed.

3.1.3. Waiting to Connect

After a successful connect( ) method invocation (one in which the URI is properly formed), the NetConnection object must wait to see if the connection attempt itself is successful. This can take some time as a number of things can happen:

  • The server may be down or unreachable, in which case the connection attempt will eventually fail.

  • The network may be slow or the server may be busy.

  • The application instance may accept the TCP network connection but place it in a pending state while it decides if it should reject or accept the connection.

Eventually, the NetConnection object is notified as to what happened via its onStatus( ) method. By default, there is no onStatus( ) method, so you should define an onStatus( ) handler before you invoke NetConnection.connect( ). The onStatus( ) method is known as an event handler or callback handler because it is invoked in response to an event occurring (in this case, the server responding to the connection attempt). The onStatus( ) handler receives an object containing information about the event that helps interpret the response.

Here is a basic onStatus( ) method that simply outputs the contents of the information object it receives:

NetConnection.prototype.onStatus = function (info) {
  trace("this.isConnected: " + this.isConnected);
  trace("      info.level: " + info.level);
  trace("       info.code: " + info.code);
  trace("info.description: " + info.description);
  if (info.application) {
    for (var prop in info.application) {
      trace("info.application." + prop + ": " + info.application[prop]);
    }
  }
  trace("\n");
};

The object received by onStaus( ), named info in this example, has three properties: level, code, and description. The level property indicates whether the event is an "error" or a "status" report. The code property provides the most meaningful information and should be used in onStatus( ) handlers to decide what action to take as events occur. The preceding example also outputs the isConnected property of the NetConnection object. If the connection has been established, isConnected is true; otherwise, isConnected is false.

Example 3-1 shows a simple test movie, followed by the output messages displayed if the connection is successful.

Example 3-1. A short test script to display connection messages
// Some credentials to pass to the application.
userName = "Guest";
password = "Guest";

// First, define an onStatus( ) handler.
NetConnection.prototype.onStatus = function (info) {
  trace("this.isConnected: " + this.isConnected);
  trace("      info.level: " + info.level);
  trace("       info.code: " + info.code);
  trace("info.description: " + info.description);
  if (info.application) {
    for (var prop in info.application) {
      trace("info.application." + prop + ": " + info.application[prop]);
    }
  }
  trace("\n");
};

// Next, create a NetConnection object.
lobby_nc = new NetConnection( );

// Finally, attempt to make the connection.
// The onStatus( ) handler will be invoked when the operation completes.
if (lobby_nc.connect("rtmp:/testLobby/", userName, password)) {
  trace("Attempting connection...");
}
else {
  trace("Can't attempt connection. Is the URI correct?");
}

If the connection is established, the code property of the information object passed to the onStatus( ) handler contains the string "NetConnection.Connect.Success":

Attempting connection...
this.isConnected: true
      info.level: status
       info.code: NetConnection.Connect.Success
info.description: Connection succeeded.

On the other hand, the connection might fail. Possible reasons for failure include that there is no testLobby application on the server or the server could not be found. In these cases, the handler reports an "error" status in the level property and additional status information is available in the code property of the information object (description is empty in this case):

Attempting connection...
this.isConnected: false
      info.level: error
       info.code: NetConnection.Connect.Failed
info.description:

The application instance can also refuse the connection request (for example, if the userName or password values are not acceptable). If the connection is rejected, the onStatus( ) method is called twicefirst with an error message and later with a status update. Note the values of the info object's level and code properties in each case:

Attempting connection...
this.isConnected: false
      info.level: error
       info.code: NetConnection.Connect.Rejected
info.description: Connection failed.
info.application.message: This application has refused your connection.

this.isConnected: false
      info.level: status
       info.code: NetConnection.Connect.Closed
info.description:

When an application instance rejects the connection attempt, it may return an object with additional information. If so, the object arrives as an application attribute of the info object passed into the onStatus( ) method. To use the application object, you need to either know its properties in advance or loop through its properties with a for-in loop as shown in Example 3-1. If you know the properties that the designer of the application script uses, they can be accessed without a for-in loop. For example, a property named message can be accessed this way:

if (info.application) {
  trace("info.application.message: " + info.application.message);
}