TOP

Red5 realizzare una chat in Flash grazie ai Remote Shared Object

Red5 Realizzare una Chat con l'ausilio dei Remote Shared Object In questo articolo illustrerò il meccanismo base per creare una chat online basata su Red5. Prima di iniziare a scrivere codice per implementare la chat, è necessario apprendere cosa sono gli Shared Object e perché sono importanti nell’ambito della creazione di applicazioni multimediali online in cui diversi utenti interagiscono tra di loro.

Partiamo com l’affermare che uno Shared Object è una specie di Super Cokie, cioè un oggetto condiviso a cui più utenti possono attingere per ottenere/memorizzare informazioni di interesse. In realtà, gli shared object sono sempre esistiti in Flash sotto il nome di “local shared object (LSO)”. Essi permettono di memorizzare dei dati actionscript nel client tramite le sessioni. In Red5 si possono usare i Remote Shared Object per condividere informazioni in real time nei filmati flash in esecuzione sui vari client. Se un filmato flash aggiorna una proprietà di un Remote Shared Object, la stessa proprietà è aggiornata in ciascun filmato flash connesso all’applicazione e di conseguenza ogni client riceve una notifica riguardo all’aggiornamento.

Esempi d’uso degli Shared Object

Gli shared object possono essere utilizzati per:

  • Notificare a tutti i filmati flash connessi a una video conferenza il nome degli stream disponibili
  • Aggiornare la posizione degli elementi in un gioco
  • Memorizzare una serie di informazioni riguardo alle proprietà degli oggetti grafici presenti in una lavagnetta condivisa
  • Gestire la lista degli utenti connessi
  • Aggiornare la lista dei messaggi scritti in una chat
Tipologie di Shared Object

I remote shared object possono essere temporanei o persistenti:

  • quelli temporanei durano solo mentre vengono utilizzati
  • quelli persistenti sono salvati nel server quando non sono utilizzati e permettono ai clienti di accedervi in un secondo momento

E’ importante capire fin da subito che gli shared object possono essere creati dal server Red5 oppure creati dal client flash. Nel nostro esempio utilizzeremo la seconda tecnica, cioè creeremo il nostro shared object da flash.

Operazioni da compiere con i Remote Shared Object

Quando si lavora con gli shared objects bisogna sapere:

  • Prelevare/Creare un remote shared object sul server Red5 utilizzando SharedObject.getRemote()
  • Gestire l’evento SharedObject.onSync in modo che il client possa aggiornarsi ad ogni cambiamento effettuato sull’oggetto condiviso
  • Connettersi allo shared object tramite il metodo SharedObject.connect
  • Modificare il valore degli slot presenti nello Shared Object se necessario
Creare uno Shared Object Remoto sul server Red5

Nel client bisogna richiamare il metodo SharedObject.getRemote(), il quale nel caso lo shared object in questione esista già sul server restituisce un riferimento ad esso, altrimenti lo crea.

var nc:NetConnection = new NetConnection();
nc.connect("rtmp://somedomain.com/applicationName");
var mySO:SharedObject = SharedObject.getRemote("mo", nc.uri, false);
mySO.connect(nc);

Gli Shared Objects memorizzano i dati in un array associativo. Le proprietà di questo array associativo vengono chiamate SLOT. Per aggiornare uno shared object con flash si utilizza la proprietà data.

clientSO.data[nameSlot] = "slot_value";
Notifiche di uno Shared Object

Quando lo slot di uno Shared Object viene creato, aggiornato o cancellato da un filmato swf, i cambiamenti vengono spediti al server Red5 e tutti i vari filmati flash client che sono collegati a questo shared object, ricevono una notifica riguardo all’aggiornamento grazie al metodo onSync. A questo metodo gli viene passato un array che contiene delle informazioni riguardo a ciò che è successo e cosa è cambiato. In particolare è presenta una proprietà “code” che indica cosa è successo, poi è presente una proprietà “name” che contiene il nome dello slot e una proprietà oldValue che contiene il valore di quello slot prima che fosse modificato. Il server può accettare o annullare la modifica di uno shared object.
I vari codici possono essere:

Codice Descrizione Nome oldValue
“success” indica che il cambiamento di uno slot da parte delf ilmato corrente è stato acettato. Gli altri filmati ricevono un “change” event per questo slot. Nome dello slot aggiornato o del nuovo slot Nessuno
“change” Uno slot è stato modificato o aggiunto da un altro filmato flash. La prima volta onSync() è chiamato dopo essersi connesso allo shared object, i valori esistenti sul server vengono copiati nello shared object del client che si connette. Nome dello slot aggiornato o del nuovo slot Indica il valore precedente oppure niente se è nuovo
“delete” Uno slot è stato cancellato o dal nostro filmato flash o da un altro. Nome dello slot cancellato. Nessuno
“reject” Il server Red5 ha respinto una modifica su uno slot dello shared object. Nome dello slot respinto. Nessuno
“clear” Tutti gli slot dello shared object sono stati cancellati. Nessuno. Nessuno

Vediamo un piccolo esempio

// Creo un oggetto NetConnection
nc = new NetConnection();
nc.connect("rtmp://myred5server/myApp");
// Creo uno shared Object
so = SharedObject.getRemote("userList", nc,true);

so.onSync = function(list) {
    for (var i = 0; i < list.length; i++) {
        switch (list[i].code ) {
            case "success":
                trace ("success");
                break;
            case "change":
                trace ("change");
                break;
            case "reject":
                trace ("reject");
                break;
            case "delete":
                trace ("delete");
                break;
            case "clear":
                trace ("clear");
                break;
        }
    }
};
Creare una chat basata su Red5

Ora che abbiamo capito cosa sono e come si utilizzano gli Shared Object vediamo come applicarli in un semplice esempio di chat.
Nel nostro caso creiamo lo Shared Object dal nostro client flash. Lato server, per ragioni di semplicità, riutilizziamo l’esempio proposto da Red5 oflaDemo. Tale esempio, se non già presente, va posizionato sotto la cartella di installazione di red5, sotto il direttorio webapps. Se non sapete come installare gli esempi, leggete questo articolo “Far funzionare gli esempi su Red5 streaming server“.
Ecco un esempio di come si presenta la Chat che potrete scaricare al termine di questo articolo.
Esempio Chat Red5

Il codice parte con la creazione dell’oggetto “nc” che utilizzeremo per connetterci al server. Dopo creiamo l’oggetto condiviso chatSO che appartiene alla classeShared Object.

// Oggetto necessario per instaurare
// la connessione al server Red5
var nc:NetConnection=new NetConnection();
// Indirizzo RTMP dell'app sul server Red5
var serverURI:String="rtmp://localhost/oflaDemo";
// Username che utilizzeremo nella chat
var username:String ="fimietta";
// Shared Object per gestire la chat
var chatSO:SharedObject;

Successivamente definiamo la funzione che instaura una connessione al server Red5:

/* GESTIONE CONNESSIONE AL SERVER */
function doConnect(){
    trace("[INFO] doConnect started");
    serverURI=server_txt.text;
    status_txt.text="[INFO]Connecting to " + serverURI +"...\n";
    nc.connect(serverURI);
}

Definiamo un handler sull’oggetto NetConnection per processare i messaggi che ci invia il server Red5 riguardo l’instaurazione della connessione. In caso di connessione avvenuta con successo (NetConnection.Connect.Success), imposto come username quella impostata nel campo di input presente nella GUI e poi si richiama la funzione getMessages la quale vedremo si collega allo shared object.

nc.onStatus = function(info){
    // Se l'instaurazione della connessione è andata a buon fine
    if(info.code=="NetConnection.Connect.Success"){
        trace("[INFO] Connessione avvenuta con successo");
        // Imposto come username corrente
        // quella digitata nel campo di input
    username = user_txt.text;
       
        // Mi connetto allo SO
                getMessages();
               
        status_txt.text+="[INFO] Connected to Red5 Server \n";
               
        }else{
            trace("[ERROR] " + info.code);
            status_txt.text+="[ERROR] " + info.code + "\n";
        }
}

Ora analizziamo la funzione getMessages. Per prima cosa creiamo/leggiamo lo shared object nominato chatSO con la funzione SharedObject.getRemote(“usersSO”,nc.uri,true);. Successivamente impostiamo l’handler onSync per essere notificati dal server Red5 ad ogni aggiornamento su chatSO. In questo caso gestiamo due tipi di notifiche: change e success. La notifica “change” la riceviamo appunto quando un altro filmato flash ha modificato chatSO mentre “succcess” la riceviamo quando il nostro filmato flash ha modificato chatSO.
Infine ci connettiamo allo SO tramite chatSO.connect(nc);.

/** GESTIONE LISTA MESSAGGI **/
function getMessages(){
    trace("[INFO] getMessages started.");
    var notified_event:String;
    var slot_msg:String="";
   
   
    // Creare uno Shared Object remoto sul server Red5
    chatSO = SharedObject.getRemote("usersSO",nc.uri,true);
   
    // Gestisco la sincronizzazione dei
    // messaggi nella chat
    chatSO.onSync = function(list){
       
        for(var i in list){
           
            slot_msg= this.data["new_message"];
            notified_event = list[i].code;
               
            switch(notified_event){
           
                case "change":
                    chatText_mc.chat_txt.htmlText +=slot_msg;
                    setScroll();
                break;
               
               
                case "success":
                    chatText_mc.chat_txt.htmlText +=slot_msg;
                    setScroll();
                break;
               
               
            }
                   
       
        }
                   
    }
   
    // Mi connetto allo Shared Object
    chatSO.connect(nc);
   
}

Ora commentiamo il codice della funzione doSend che è quella che si occupa di spedire il nostro messaggio di chat al server Red5. In realtà la funzione è molto semplice perché legge il messaggio digitato nel campo di input “send_txt” e lo memorizza in una variabile chiama “msg” e poi scriviamo su uno slot che chiamiamo new_message il valore di msg, ricordandoci che lo SO non è altro che un array associativo: chatSO.data["new_message"]=msg;

function doSend(){
    trace("doSend");
    var msg:String;
   
    msg =  "<p><b>[" + username + "]:</b> " + chatText_mc.send_txt.text  + "</p>";
   
    // Manda il messaggio
    chatSO.data["new_message"]=msg;
   
    //Azzero il campo testo
    chatText_mc.send_txt.text="";
   
}
Codice Completo
// Oggetto necessario per connettersi al server
var nc:NetConnection=new NetConnection();
// Indirizzo RTMP dell'app sul server Red5
var serverURI:String="rtmp://localhost/oflaDemo";
// Username utilizzato nella chat
var username:String ="fimietta";
// Shared Object per gestire la chat
var chatSO:SharedObject;

// Aggiungo la proprietà
// max scroll
chatText_mc.maxscroll=1000;



// Init Campi di Input
user_txt.text="myusername";

server_txt.text="rtmp://localhost/oflaDemo";


/** Gestione Eventi ***/

// Pulsante connetti
connect_btn.onPress = function(){
    doConnect();
   
}

// Pulsante Invia
chatText_mc.send_mc.onPress= function(){
    doSend();
}

chatText_mc.send_txt.onSetFocus = function(oldFocus:Object) {
    Key.addListener(myBugObj);
}

chatText_mc.send_txt.onKillFocus = function(oldFocus:Object){
    Key.removeListener(myBugObj);
}

var myBugObj = {};

myBugObj.onKeyDown = function(){
    if (Key.getCode() == 13 || Key.isDown(Key.ENTER)){
            doSend();
    }
};
           





/* GESTIONE CONNESSIONE AL SERVER */
function doConnect(){
    trace("[INFO] doConnect started");
    serverURI=server_txt.text;
    status_txt.text="[INFO]Connecting to " + serverURI +"...\n";
    nc.connect(serverURI);
}


nc.onStatus = function(info){
       
        // Se l'instaurazione della connessione è andata a buon fine
        if(info.code=="NetConnection.Connect.Success"){
                trace("[INFO] Connessione avvenuta con successo");
           
                username = user_txt.text;
               
                getMessages();
               
                status_txt.text+="[INFO] Connected to Red5 Server \n";
               
        }else{
            trace("[ERROR] " + info.code);
            status_txt.text+="[ERROR] " + info.code + "\n";
        }
}


/*** GESTIONE CHAT ***/

// Funzione che invia il messaggio della chat
function doSend(){
    trace("doSend");
    var msg:String;
   
    msg =  "<p><b>[" + username + "]:</b> " + chatText_mc.send_txt.text  + "</p>";
   
    // Manda il messaggio
    chatSO.data["new_message"]=msg;
   
    //Azzero il campo testo
    chatText_mc.send_txt.text="";
   
}


/** GESTIONE LISTA MESSAGGI **/
function getMessages(){
    trace("[INFO] getMessages started.");
    var notified_event:String;
    var slot_msg:String="";
   
   
    // Creare uno Shared Object remoto sul server Red5
    chatSO = SharedObject.getRemote("usersSO",nc.uri,true);
   
    // Gestisco la sincronizzazione dei
    // messaggi nella chat
    chatSO.onSync = function(list){
       
        for(var i in list){
           
            slot_msg= this.data["new_message"];
            notified_event = list[i].code;
               
            switch(notified_event){
           
                case "change":
                    chatText_mc.chat_txt.htmlText +=slot_msg;
                    setScroll();
                break;
               
               
                case "success":
                    chatText_mc.chat_txt.htmlText +=slot_msg;
                    setScroll();
                break;
               
               
            }
                   
       
        }
                   
    }
   
    // Mi connetto allo Shared Object
    chatSO.connect(nc);
   
}

function setScroll(){
    chatText_mc.chat_txt.scroll = chatText_mc.chat_txt.maxscroll;
    chatText_mc.chatScroll.setScrollTarget(chatText_mc.chat_txt);
    chatText_mc.chatScroll.setScrollPosition(chatText_mc.chat_txt.maxscroll);

}
Download

4 comments. Leave a Reply

  1. Gianluca

    Ciao, veramente grazie, inoltre complimenti. La guida oltre ad avermi aperto un mondo è molto esaustiva.

    spesso però facendo un trace dello slot del messaggio questo appare vuoto ed in effetti il ricevente non riceve (scusa il gioco di parole) niente (sebbene gli venga segnalato la modifica dello stato in “change”)

    è un errore noto o solo mio?

    Grazie e buona serata

    • Bene sono contenta che sia utile questo tutorials.
      Ma ti stai riferendo a questo esempio specifico?

  2. Gianluca

    Buona giornata
    Ti ringrazio per la risposta.
    Dunque alla fine ne sono venuto a capo. questo fenomeno capitava quando il messaggio precedente era uguale al nuovo messaggio.
    Leggendo un po la documentazione ho trovato che l’handler onSync non viene richiamato se lo stesso client attiva lo stesso evento con lo stesso valore (leggo che il motivo è limitare il traffico)

  3. manuel

    ciaooo

Leave a Reply

Your email is never published nor shared.

You may use these HTML tags and attributes:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>