Connection FMS3 via RTMPConnection

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par gauthier (Gauthier de Girodon Pralong), le 04 mars 2010

Bonjour, nous allons voir ici comment se connecter à un serveur de type rtmp (nous prendrons pour exemple flash media interactive server version 3.5). Ici nous n'aborderons pas le développement d'application serveur mais juste la connexion avec ce dernier. Nous verrons aussi les avantages que peut nous fournir l'api RTMPConnection.

page du projet : http://rtmpconnection.googlecode.com

swc : http://rtmpconnection.googlecode.com/files/RTMPConnection.swc

svn : http://rtmpconnection.googlecode.com/svn/trunk/

video : http://blogauth.mediabox.fr/post/2010/03/09/Commencer-avec-l-api-RTMPConnection

Comment se Connecter

Afin de nous connecter à une application du nom de “test” sur server local rtmp via actionscript nous devons utiliser un Objet NetConnection comme ceci :

Standard

var nc:NetConnection = new NetConnection()
nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
nc.connect("rtmp://localhost/test");
 
//ici nous regardons si nous avons réussi a nous connecter
private function onStatus(e:NetStatusEvent):void{
      if(e.info.code=="NetConnection.Connect.Success"){
             trace("connecté");
       }
}

Avec l'api

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
 
var nc:RTMPConnection = new RTMPConnection();
nc.application = "test";
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
nc.connection();
 
//ici nous regardons si nous avons réussi a nous connecter
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
}

Nous avons précisé avec l'api l'application à laquelle l'objet RTMPConnection devait se connecter via la propriété application. Par défaut l'objet RTMPConnection se connecte au server situé sur localhost. Pour se connecter à un server distant il suffit d'indiquer l'ip du server.

nc.ip = "ip du server";

vous pouvez aussi vous connecter comme ceci

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
 
var nc:RTMPConnection = new RTMPConnection("test","localhost");
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
nc.connection();
 
//ici nous regardons si nous avons réussie a nous connecter
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
}

Voilà nous savons maintenant comment nous connecter simplement à une application sur un server rtmp. Mais pourquoi utiliser RTMPConnection plutôt que l'objet NetConnection ? Nous allons voir ça maintenant

Pourquoi RTMPConnection

RTMPConnection repose principalement sur un héritage de la classe NetConnection, mais j'y ai rajouté quelques fonctionnalités qui lors de mes développement m'ont permis d'aller un peu plus vite.

Evènements

Premièrement la gestion des évènements est simplifiée via l'api comme vous allez le voir tout de suite.
Si je devais tester les différents état lors de ma connection je devrais passer par une méthode qui exécuterait à chaque fois des actions suivant l'état.

exemple :

var nc:NetConnection = new NetConnection()
nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
nc.connect("rtmp://localhost/test");
 
//ici nous regardons si nous avons réussi a nous connecter
private function onStatus(e:NetStatusEvent):void{
      switch(e.info.code){
          case "NetConnection.Connect.Success":
                trace("connecté");
          break;
          case "NetConnection.Connect.Closed":
                trace("fermé");
          break;
          case "NetConnection.Connect.Rejected":
                trace("rejeté");
          break;
          etc...
     }
}

Personnellement je n'aime pas trop ce genre de gestion, mais c'est un point de vue. Cependant c'est ce que fait l'api en interne. La différence c'est qu'elle me signalera l'état via un event, et je pourrais ainsi directement assigner une méthode à exécuter suivant l'état.

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
 
var nc:RTMPConnection = new RTMPConnection();
nc.application = "test";
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
nc.addEventListener(RTMPEvent.CLOSED, onClosed);
nc.addEventListener(RTMPEvent.REJECTED, onRejected);
nc.connection();
 
 
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
}
 
private function onClosed(e:RTMPEvent):void{
   trace("fermé");
}
 
private function onRejected(e:RTMPEvent):void{
   trace("rejeté");
   trace("raison "+e.info.rejectReason)
}

Reconnexion automatique

Maintenant imaginons que vous ayez besoin de gérer un système de reconnexion automatique. L'api permet de gérer ça très facilement comme nous allons le voir.

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
import gauthier.net.rtmp.events.AttemptEvent;
 
var nc:RTMPConnection = new RTMPConnection();
nc.application = "test";
nc.maxAttempt = 3;
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
nc.addEventListener(RTMPEvent.CLOSED, onClosed);
nc.addEventListener(RTMPEvent.REJECTED, onRejected);
//appeler lors de chaque reconnection
nc.addEventListener(AttemptEvent.ATTEMPT, onAttempt);
//appeler une fois le nombre maximum de reconnection atteint
nc.addEventListener(AttemptEvent.ATTEMPT_END, onAttemptEnd);
nc.connection();
 
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
}
 
private function onClosed(e:RTMPEvent):void{
   trace("fermé");
}
 
private function onRejected(e:RTMPEvent):void{
   trace("rejeté");
   trace("raison "+e.info.rejectReason)
}
 
private function onAttempt(e:AttemptEvent):void{
    trace("reconnexion #"+e.attemptObject.currentCount+" sur "+e.attemptObject.countMAX);
}
private function onAttemptEnd(e:AttemptEvent):void{
   trace("reconnexion impossible");
}

Pour utiliser le système de reconnexion automatique il nous faut obligatoirement définir la propriété maxAttempt qui correspond au nombre de tentatives de reconnexion. Dans l'exemple ci-dessus je tenterais 3 fois de me reconnecter lors d'un rejet ou d'une perte de connexion. une valeur négative (-1 par exemple) indique que nous tenterons de nous reconnecter indéfiniment, à savoir que dans ce cas évènement AttemptEvent.ATTEMPT_END n'est jamais envoyé.

Par défaut le délai entre chaque reconnection et de 1 seconde. Mais nous pouvons modifier cette valeur grâce à la propriété delay. Les valeur sont exprimées en seconde.
Exemple :

//tentera une reconnexion toutes les 5 secondes
nc.delay = 5;

Attention
Avec le système d'autoconnect vous ne pouvez pas utiliser la méthode close() pour fermer une connection. Effectivement si vous appelez close() sur votre objet RTMPConnection et que l'autoconnect est activé, RTMPConnection retentera une connexion automatiquement. Pour forcer l'arrêt d'une connection alors que le mode autoconnect est activé vous devez passer par la méthode closeByAction(). Ainsi vous êtes sûrs de couper la connexion et d'arrêter le mode autoconnect.

Connection en tant qu'Administrateur

Il se peut que vous ayez besoin de vous connecter en tant qu'administrateur à votre server rtmp. Pour se faire rien de bien compliqué, il vous suffit de procéder ainsi:

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
 
var nc:RTMPConnection = new RTMPConnection();
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
nc.addEventListener(RTMPEvent.CLOSED, onClosed);
nc.addEventListener(RTMPEvent.REJECTED, onRejected);
nc.connection("votre login admin", "votre mot de pass admin");
 
 
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
}
 
private function onClosed(e:RTMPEvent):void{
   trace("fermé");
}
 
private function onRejected(e:RTMPEvent):void{
   trace("rejeté");
   trace("raison "+e.info.rejectReason)
}

Détection automatique de la Bande Passante

Voici comment procéder pour détecter la bande passante de votre client:

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
import gauthier.net.rtmp.events.BWEvent;
 
var nc:RTMPConnection = new RTMPConnection();
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
nc.addEventListener(BWEvent.ON_BW, onBandWidthDetected);
nc.connection();
 
private function onBandWidthDetected(e:BWEvent):void{
   trace("bw detected "+e.bwObject.Kbits+" kbps");
}
 
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
   //ici on lance la detection
   (e.target as RTMPConnection).checkBandWidth();
}
 
}

Attention toutefois, si vous définissez un objecta client à votre objet RTMPConnection vous devrez définir les fonctions onBWDone et onBWCheck dans votre objet.

exemple :

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
import gauthier.net.rtmp.events.BWEvent;
 
var nc:RTMPConnection = new RTMPConnection();
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
//nc.addEventListener(BWEvent.ON_BW, onBandWidthDetected);  <--- ceci ne marchera plus
nc.client = this; //ici j'ai delcaré mon client 
nc.connection();
 
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
   //ici on lance la detection
   (e.target as RTMPConnection).checkBandWidth();
}
 
public function onBWCheck(... rest):Number
   return 0;
}
public function onBWDone(... rest):void { 
  var p_bw:Number; 
  if (rest.length > 0)  
  p_bw = rest[0]; 
  trace("bandwidth = " + p_bw); 
}

Connexion au server Stratus (P2P)

Avec RTMPConnection vous pouvez vous connecter au server stratus via votre clé de développeur. Pour obtenir une clé de développeur cliquez ici –> http://labs.adobe.com/technologies/stratus/ .Il vous suffit ensuite de définir votre clé à l'objet RTMPconnection comme ceci

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
 
var nc:RTMPConnection = new RTMPConnection();
nc.devKey = "ma dev key ";// ici on definit sa clé de developper
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
nc.connection();
 
private function onSuccess(e:RTMPEvent):void{
   trace("connecté a stratus");
   trace("voici ma peerID"+ (e.target as RTMPConnection).nearID);
}

Connexion via Fichier de configuration

Vous pouvez créer un fichier de configuration externe par exemple pour paramétrer votre connexion. Par défaut l'api prend en charge le format xml et json. Voici deux exemples complets de fichier de configuration .

FORMAT XML

<config>
        <ip>ip du server</ip>
        <port>pour du server</port>
        <protocol>protocole de la connexion</protocol>
        <application>nom de l'application</application>
        <maxAttempt>nombre de reconnexion</maxAttempt>
        <delay>mon delais entre chaque reconnexion (en seconde)</delay>
        <devKey>ma cle de dev</devKey>
        <login>mon login d'aministrateur</login>
        <password>mon password d'administrateur</password>
</config>

FORMAT JSON

{ 
"ip" : "ip du server",
"port" : pour du server,
"protocol" : "protocole de la connexion",
"application" : "nom de l'application",
"maxAttempt"  : nombre de reconnexion,
"delay" : mon delais entre chaque reconnexion (en seconde),
"devKey" : "ma cle de dev",
"login" : "mon login d'aministrateur",
"password" : "mon password d'administrateur"
}

UTILISATION

Pour charger un fichier de configuration rien de plus simple, il vous suffit d'indiquer quel est le type de configuration (xml, json… par défaut le format est le xml) et de charger le fichier dans votre RTMPConnection comme ci-dessous :

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
//import gauthier.net.rtmp.config.RTMPConfigType;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
 
private var __nc:RTMPConnection;
 
private function init():void{
   __nc= new RTMPConnection();
 //__nc.configType = RTMPConfigType.JSON; si mon fichier de config était de type json
   __nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
   __nc.addEventListener(RTMPEvent.FAILED, onFailed);
   __nc.addEventListener(RTMPEvent.REJECTED, onReject);
   loadConfiguration();         
}
 
///ici je lance le chargement
private function loadConfiguration():void{
   var uld:URLLoader= new URLLoader()
   uld.addEventListener(Event.COMPLETE, onComplete);
   uld.load(new URLRequest("myconfig.xml"));
}
 
///une fois le fichier chargé je l'envois a ma connection et je fais la connection
private function onComplete(e:Event):void{
   __nc.configuration = (e.target as URLLoader).data;
   __nc.connection();
}
 
private function onConnect(e:RTMPEvent):void{
   trace("yeahhh je suis connecté");
}
 
private function onFailed(e:RTMPEvent):void{
   trace("arf, j'ai du me planter quelque part");
}

Divers

Passer des paramètres lors de la connexion

Lors d'une connexion a une application rtmp nous pouvons passer un ou plusieurs paramètres, par exemple pour effectuer une identification coté server.

Voici comment procéder :

import gauthier.net.rtmp.events.RTMPEvent;
import gauthier.net.rtmp.RTMPConnection;
 
var nc:RTMPConnection = new RTMPConnection("test");
nc.addEventListener(RTMPEvent.SUCCESS, onSuccess);
 
nc.addClientParam("admin"});// un login par exemple
nc.addClientParam("1234"); // un mot de passe
nc.connection();
 
//ici nous regardons si nous avons réussie a nous connecter
private function onSuccess(e:RTMPEvent):void{
   trace("connecté");
}

main.asc cote server

application.onConnect = function(client, login, password)
{
    if(login == "admin" && password =="1234"){
        this.acceptConnection(client);
    }else{
        var error = new Object();
	error.message = "vous n'êtes pas identifié"; 
	this.rejectConnection(client, error);
    }
}

Vous pouvez passer n'importe quel type d'objet en parametre evidemment.