Fare Http Streaming consiste nel cambiare l'approccio di comunicazione con il server, si passa dal Polling al Pushing, in modo da rimanere sempre in ascolto e lasciare che sia il server ad inviarci un flusso continuo di dati.
In una comunicazione di tipo polling, che è quella alla base della comunicazione Client-Server, in linea generale:
1. Scriviamo l'url della risorsa che desideriamo ricevere
2. Arriva la richiesta al server che la elabora e ci risponde
3. il browser legge e interpreta la risposta del server e ci fa vedere il risultato.
Già al termine del 2° punto la comunicazione con il server è chiusa e bisogna ripetere la procedura per avere accesso di nuovo alla risorsa.
Con AJAX non facciamo altro che ripetere questi 3 punti, ma in maniera asincrona, effettuano la richiesta con l'oggetto XMLHttpRequest e poi elaborando come meglio crediamo i risultati (che possiamo ricevere da 2 metodi: responseXML e responseText)
Se volessimo implementare una chat in PHP e AJAX dovremmo fare delle continue richieste al server per sapere se ci sono o meno nuovi messaggi e visualizzarli,stesso discorso per un sistema di monitoraggio ecc.ecc.
Con un Server Push (o pushing) evitiamo queste continue richieste mantenendo aperto un canale di comunicazione con il server, che ci invierà un flusso continuo di dati...
Vediamo come:
L'esempio è molto banale...e il codice non ottimizzato, ha solo uno scopo dimostrativo.
Ecco il contenuto del Javascript che richiama la risorsa sul server e ne legge il flusso di ritorno
codice:
<script language="javascript" type="text/javascript">
var url = 't.php';
if(window.XMLHttpRequest)
{ XmlHttp = new XMLHttpRequest();
XHRprovider = 'FF';
}
else
if(window.ActiveXObject)
{ try { XmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
XHRprovider = 'IE';
}
catch(e)
{ XmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
XHRprovider = 'IE';
}
}
else { alert("NO XMLHttpRequest Object");}
function OpenSend (url)
{ XmlHttp.open('GET', url, true);
XmlHttp.setRequestHeader('x-arrt-xhrprovider', XHRprovider);
XmlHttp.send(null);
}
OpenSend (url);
KeepsReading = window.setInterval( function()
{ switch (XmlHttp.readyState)
{ case 3: if (XHRprovider=='FF') ShowStreaming (XmlHttp.responseText);
break;
case 4: // Solo IE
ShowStreaming (XmlHttp.responseText);
XmlHttp.Abort();
OpenSend(url);
break;
}
},500);
function ShowStreaming (dati)
{ document.getElementById('streaming').innerHTML=dati;
}
</script>
lo script PHP che manda il flusso è ovviamente un loop
Codice PHP:
header ("Expires: Tue, 01 Jan 1980 00:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-store, no-cache, must-revalidate");
header ("Cache-Control: post-check=0, pre-check=0", false);
header ("Pragma: no-cache");
header ("Content-type: text/html; charset=iso-8859-1");
$headers = apache_request_headers();
$_XHRprovider =(array_key_exists("x-arrt-xhrprovider",$headers))?$headers['x-arrt-xhrprovider']:"FF";
$exit=false;
while ( (true)&&(!$exit) )
{ echo gmdate("D, d M Y H:i:s")."
";
if ($_XHRprovider=="IE")
{ $exit=true; }
else
{ ob_flush();
flush();
sleep(1);
}
}
commentiamo...
nel codice JS come avrete notato non viene più richiamato il metodo onreadystatechange perchè in effeti non ci serve più... abbiamo fatto noi una funzione che periodicamente legge l'output...
nello script PHP si ha un loop... all'interno ovviamente ci faccimo quello che vogliamo potremmo ad esempio estrapolare dal DB il numero di messaggi spediti nella chat, le quotazioni in borsa ecc ecc...
ma veniamo alle note dolenti....
in FireFox (ma dovrebbe andare per tutti i browser che supportano nativamente l'oggetto XMLHttpRequest) si verifica un vero e proprio streaming....
il metodo readyState dell'oggetto XMLHttpRequest resta fermo allo stato 3 (comunicazione in corso) e noi riceviamo continuamente i dati con un flusso continuo...
inInternet Explorer (ovviamente) questo non avviene....
ciò perchè IE non restituisce nulla, sopprime il metodo responseText,finche la comunicazione non termina e cioè finchè non si arriva allo stato 4
che dire....
Io mi sono incazzato perchè questa tecnica di streaming mi sarebbe ritornata mooooolto comoda in un lavoro che dovrò consegnare tra non molto....e quindi ho tirato giù dal calendario un paio di Santi
su Ajax Pattern, da cui prende spunto la pillola, sono un tantino più diplomatici e dicono:
"You could claim that's either a bug or a feature; but either way, it works against HTTP Streaming."
Nel codice come avrete notato c'è un piccolo hack per IE:
ovvero mando al server anche un header ad hoc che lo informa che sta avendo a che fare con un caca browser e che quindi dopo i primi dati e inutile che lavora ed è meglio che esce...
restituendo così i dati e chiudendo la comunicazione
in JS il metodo readyState passa llo stato 4
prendo i dati li visualizzo e faccio ripartire subito un'altra chiamata al server...
ovviamente non è più streaming questo!
a voi la decisione se usare questa tecnica o meno...
giusto per completezza di informazione,
ci sono delle applicazioni (alcune free in JAVA) che raggirano il problema .... ma sono un'altra cosa...sono delle applicazioni StandAlone sul server, in ascolto su una porta, che gestiscono internamente il flusso di dati in uscita e le varie connessioni aperte...insomma un vero e prorio server push.
quello che ho proposto è una simulazione di un server push... e che se IE si comportasse bene....sarebbe una grande cosa: netta diminuzione delle chiamate al server con conseguente minor carico di Apache e la possibilità di ricevere in (quasi) real-time un flusso di informazioni.
non ho testato non IE 7, se qualcuno prova mi fa sapere
se avete idee in merito su come poter risolvere con IE.....parliamoneeee...