Developer Resources:

Customer Quotes:

Introduction

RTMP (Real-Time Messaging Protocol) is a binary protocol supported by Flash Player which enables fast, efficient, bidirectional communication between Flex/Flash clients and server-side applications. The protocol supports data messaging for various message exchange paradigms (client-to-client(s), client-to-server, server-to-client(s) and server-to-server) as well as media (video and audio) streaming and recording. WebORB for .NET supports the RTMP protocol and provides facilities to enable data message exchanges mentioned above as well as video streaming and recording. This articles describes the setup, configuration and APIs for implementing a data push from the .NET code to all connected clients.

To get started make sure you have the following software installed:

  • Flash Builder version 4
  • WebORB for .NET version 3.6.0.3 or later
  • Microsoft Visual Studio 2008 or later
  • Microsoft .NET framework v. 2.0 or later 

Project Description

To demonstrate server-to-client data push over RTMP, the article will use a Flex application which displays a chart of the server's CPU allocation. The CPU readings will be read by .NET code and delivered to the client using WebORB's Messaging (RTMP) infrastructure. The diagram below illustrates the process:

Project development will consist of two parts:

  1. Flex client code connecting to the server and subscribing to receive server-side updates with the CPU readings. The code also includes a chart to visualize the received data.
  2. The server-side 'Application handler' which plugs into WebORB, polls CPU and delivers data to the client.

Developing .NET Code

WebORB Messaging infrastructure has an abstraction of 'application handler'. An application handler represents a messaging application also referred to as application scope. When a client connects to the server, it must specify the application by name. Application scope shares all the context managed within the application, provides access to all the client connections and shared objects. The code below is the application handler for the CPU Monitoring example reviewed in this article:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Diagnostics;
   6:  using System.Timers;
   7:   
   8:  using Weborb.Messaging.Api.Service;
   9:  using Weborb.Messaging.Api;
  10:  using Weborb.Messaging.Server.Adapter;
  11:   
  12:  namespace CPUMonitor
  13:  {
  14:    public class CPUMonitoringAppHandler : ApplicationAdapter
  15:    {
  16:      private Timer cpuReadingTimer;
  17:      private PerformanceCounter cpuCounter;
  18:   
  19:      // invoked when WebORB for .NET starts up
  20:      public override bool appStart( IScope app )
  21:      {
  22:        bool appStarted = base.appStart( app );
  23:   
  24:        // if application could not start for any reason, do not proceed further
  25:        if( !appStarted )
  26:          return appStarted;
  27:   
  28:        // initialize performance counter
  29:        cpuCounter = new PerformanceCounter();
  30:        cpuCounter.CategoryName = "Processor";
  31:        cpuCounter.CounterName = "% Processor Time";
  32:        cpuCounter.InstanceName = "_Total";
  33:   
  34:        // start thread to get CPU readings
  35:        cpuReadingTimer = new Timer( 1000 );
  36:        cpuReadingTimer.Elapsed += new ElapsedEventHandler( cpuReadingTimer_Elapsed );
  37:        return appStarted;
  38:      }
  39:   
  40:      void cpuReadingTimer_Elapsed( object sender, ElapsedEventArgs e )
  41:      {
  42:        // ignore timer event, if there are no connected clients to the scope
  43:        if( scope.getClients().Count == 0 )
  44:          return;
  45:   
  46:        // get the CPU reading
  47:        float cpuUtilization = cpuCounter.NextValue();
  48:   
  49:        // create an array of values to deliver to the client.
  50:        // there is only one value, but the API requires it to be an array
  51:        object[] args = new object[] { cpuUtilization };
  52:   
  53:        // get an enumeration of connections to this application
  54:        IEnumerator<IConnection> connections = scope.getConnections();
  55:   
  56:        while( connections.MoveNext() )
  57:        {
  58:          IConnection connection = connections.Current;
  59:   
  60:          // invoke client-side function to deliver CPU reading
  61:          if( connection is IServiceCapableConnection )
  62:            ((IServiceCapableConnection) connection).invoke( "processCPUReading", args );
  63:        }
  64:      }
  65:    }
  66:  }

The CPUMonitoringAppHandler class is the application handler for the messaging application. The class must extend the ApplicationAdapter class. (The base class is in the Weborb.Messaging.Server.Adapter namespace). CPUMonitoringAppHandler declares and creates a timer (lines 16 and 35-36). The timer wakes up every second and checks if the application has any connected clients (line 43). If there is at least one client, the timer event gets the latest CPU reading using PerformanceMonitor API (line 47) and subsequently delivers the reading value to all connected clients (lines 54-63).

The handler class can be compiled as a class library and deployed into the default WebORB installation folder. See the "Introduction to Flex and .NET integration" article for the deployment instructions. You can also download a Visual Studio solution with the source code for the .NET part of the project (make sure to add a project reference to weborb.dll).

Registering Messaging Application

Once the assembly with the application handler is deployed, it must be registered as a messaging application. The instructions below describe the process:

  1. Locate the /Applications folder in the root of your WebORB installation. If you use WebORB version 3 for .NET, the folder is located in /inetpub/wwwroot/weborb30/. If you use WebORB version 4 for .NET, the folder is under /Program Files/WebORB/4.0/
  2. Create CPUMonitoringApp subfolder under Applications/. The name of the folder is going to be the name of the application. This is the name Flex clients will use to connect to the server/application.
  3. Download this file and extract its contents into the CPUMonitoringApp directory. Once you do that the directory should have app.config file inside. For the verification purposes, open app.config and make sure the name of the class in the application-handler element matches the full type name of your application handler.
  4. You can use WebORB Management Console to verify if the messaging application is properly deployed. if you use WebORB version 3 select Management and then Messaging Server. The name of the application (CPUMonitoringApp) should appear in the list of application. With version 4 of WebORB, you should see the name of the application on the main overview screen.

Developing Flex Code

Using Flash Builder create a Flex project as described in the "Introduction to Flex and .NET integration" article. If you are using Flex Builder, see the "Setting up Flex Builder to work with WebORB" article for the instructions on how to create and configure a Flex project to work with WebORB.

Consider the MXML/ActionScript code below:

   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
   3:           xmlns:s="library://ns.adobe.com/flex/spark" 
   4:           xmlns:mx="library://ns.adobe.com/flex/halo"
   5:           creationComplete="init()">
   6:    <fx:Declarations>
   7:    </fx:Declarations>
   8:    <fx:Script>
   9:    <![CDATA[
  10:      import mx.collections.ArrayCollection;
  11:      import mx.controls.Alert;
  12:      
  13:      [Bindable]
  14:      private var cpuValues:ArrayCollection = new ArrayCollection();
  15:      private var serverConnection:NetConnection;
  16:      
  17:      private function init():void
  18:      {
  19:        serverConnection = new NetConnection();
  20:        serverConnection.addEventListener(NetStatusEvent.NET_STATUS, handleStatus );
  21:        serverConnection.client = this;
  22:        serverConnection.connect( "rtmp://localhost:2037/CPUMonitoringApp" );
  23:        
  24:        for( var i:int = 0; i < 100; i++ )
  25:          cpuValues.addItem( 0 );
  26:      }
  27:      
  28:      private function handleStatus( evt:NetStatusEvent ):void
  29:      {
  30:        switch( evt.info.code )
  31:        {
  32:          case "NetConnection.Connect.Success":                
  33:            break;
  34:          case "NetConnection.Connect.Failed":
  35:            Alert.show( "Unable to connect to WebORB", "Connection Error" );
  36:            break;                                
  37:        }
  38:      }
  39:      
  40:      public function processCPUReading( cpuUtilization:Number ):void
  41:      {
  42:        // create sliding chart effect
  43:        cpuValues.removeItemAt( 0 );
  44:        cpuValues.addItem( cpuUtilization );
  45:      }
  46:    ]]>
  47:    </fx:Script>
  48:    <s:Panel left="5" right="5" top="5" bottom="5" 
  49:             title="Server CPU Utilization">
  50:      <mx:LineChart id="cpuChart" 
  51:                    left="10" right="10" top="10" bottom="10"
  52:                    dataProvider="{cpuValues}">
  53:        <mx:series>
  54:          <mx:LineSeries displayName="CPU(%)" yField=""/>
  55:        </mx:series>
  56:      </mx:LineChart>
  57:    </s:Panel>
  58:  </s:Application>

The client code uses the NetConnection API to connect to the server and receive server-to-client (DataPush) callbacks. The "serverConnection" variable is declared on line 15 and initialized on lines 19-22. Notice the URL of the messaging application on line 22. The "CPUMonitoringApp" part of the URL refers to the messaging application created earlier in the article. It is also important to note the assignment on line 21. The "client" property on NetConnection refers to the object which contains the methods invoked from the server-side. In this example, the same object (the Flex application itself) hosts the method invoked on the server. The method is "processCPUReading" (lines 40-45). The method receives an argument value delivered by the server. The value is stored in a bindable ArrayCollection - variable "cpuValues". The chart (lines 50-56) uses cpuValues as the data provider. As soon as the code updates the values in the array collection, the chart is automatically updated. 

Download full MXML listing of the example.

Running the Example

When you run the example, you should immediately see data in the chart. You can try running multiple browsers with the example application. If the data does not arrive, make sure the WebORB messaging server is running - you can do that by opening the WebORB Management Console.