My Day at the Beach
Today I went to the beach and had a lot of fun.
...more content...
here comes a title
Wake up sheeple!
Last Modified:
My Day at the Beach
Today I went to the beach and had a lot of fun.
...more content...
...more blog posts...
==== Les APIs ====
De plus, HTML5 apporte une suite d'APIs intéressantes qui
interface WebSocket {
readonly attribute DOMString url;
// ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSING = 2;
const unsigned short CLOSED = 3;
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;
// networking
attribute Function onopen;
attribute Function onmessage;
attribute Function onerror;
attribute Function onclose;
readonly attribute DOMString protocol;
void send(in DOMString data);
void close();
};
==== Côté serveur ====
Dans le cadre des quelques démonstrations qui vont suivre, nous allons utiliser une librarie ''php'' disponible sur [[https://github.com/nicokaiser/php-websocket/tree/master/server|github]]. Toutefois, il existe déjà d'autres implémentations de serveur websockets en [[http://jwebsocket.org/|Java]], en [[https://github.com/igrigorik/em-websocket|Ruby]],...
==== Côté client ====
Afin de pouvoir satisfaire tout le monde (c-à-d ceux qui n'utilisent pas
var wsConnection = new WebSocket('ws://monserveur.com:8080/application');
Le reste du code va simplement permettre de définir les méthodes ''onopen'', ''onclose'', ''onmessage'' et ''onerror'' de l'objet ''websocket''. On peut noter que la grande partie du code est utilisé pour l'esthétique de l'interface.
wsConnection.onopen = function (evt) {
console.log('Websocket open.');
$('#status').removeClass().addClass('online').html('online');
writeToScreen('connected to '+ wsUri)
$('#send').attr('disabled', false);
}
wsConnection.onclose = function(evt) {
console.log('Websocket closed.');
$('#status').removeClass().addClass('offline').html('offline');
$('#send').attr('disabled', true);
}
wsConnection.onmessage = function(evt) {
console.log('Message received.')
writeToScreen('Received: ' + evt.data);
output.animate({scrollTop: output.attr('scrollHeight')})
}
wsConnection.onerror = function(evt) {
console.error('Error with the socket')
$('#status').removeClass().addClass('error').html('error');
}
=== Côté serveur ===
Du point de vue du serveur, tout est très simple. Nous avons enregistré une nouvelle application et avons définis quelques méthodes au sein de celle-ci. Cette application va gérer la (dé)connexion des clients et leur répondre la date uniquement à leur demande.
class DateApplication extends Application
{
private $clients = array();
private $lastTime = 0;
public function onConnect($client) {
$this->clients[] = $client;
}
public function onDisconnect($client) {
$key = array_search($client, $this->clients);
if ($key) {
unset($this->clients[$key]);
}
}
public function onData($data, $client) {
$client->send(date(DATE_RFC822));
}
}
==== 2 - Date from server ====
[[http://poulpe.heig-vd.ch/masrad/websockets/2-date|Lien sur l'application]]
=== Description ===
Le fonctionnement de cette application diffère de l'exemple précédent. Cette fois-ci, c'est le serveur qui va interagir avec le(s) client(s) connecté(s). Lors de l'ouverture de l'exemple, l'application va ouvrir une connexion sur le serveur. Celui-ci va enregistrer le client dans une liste puis, toutes les 3 secondes, le serveur va transmettre la date à **tous** les clients
=== Coté Serveur ===
public function onTick() {
if (time() >= $this->lastTime + 3) {
$this->lastTime = time();
foreach ($this->clients as $sendto) {
$sendto->send(date(DATE_RFC822));
}
}
}
====3 - Simple IRC ====
[[http://poulpe.heig-vd.ch/masrad/websockets/3-irc|Lien sur l'application]]
Télécharger l'exemple: {{:ajax:3-irc-simple.zip|}}
=== Description ===
Cet exemple a pour but de créer un mini chat. Il faut alors que le serveur soit en mesure :
* D'enregistrer les nouveaux clients.
* Broadcaster l'arrivée de quelqu'un.
* Broadcaster les messages des utilisateurs .
* Gérer la déconnexion d'un utilisateur.
De leur côté, les clients doivent être en mesure de :
* Effectuer une connexion au serveur
* Transmettre des messages au serveur
* Lire les messages reçu
=== Côté Client ===
var wsUri = "ws://monserveur:monport/application";
var output;
$(document).ready(function() {
output = $("div#log");
initWebSocket();
$('#send').click(function(){
console.log('Message sent: ' + $('#message').val());
writeToScreen("Websocket called");
websocket.send($('#message').val());
});
});
function initWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function (evt) {
console.log('Websocket open.');
$('#status').removeClass().addClass('online').html('online');
writeToScreen('connected to '+ wsUri)
$('#send, #message').attr('disabled', false);
}
websocket.onclose = function(evt) {
console.log('Websocket closed.');
$('#status').removeClass().addClass('offline').html('offline');
$('#send, #message').attr('disabled', true);
$('#connection').text('Connect');
setTimeout(initWebSocket, 1000);
}
websocket.onmessage = function(evt) {
console.log('Message received.')
var data = JSON.parse(evt.data);
writeToScreen('['+data.who+']: ' + data.msg);
output.animate({scrollTop: output.attr('scrollHeight')})
}
websocket.onerror = function(evt) {
console.error('Error')
$('#status').removeClass().addClass('error').html('error');
}
}
function writeToScreen(message) {
var pre = document.createElement("pre");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.append(pre);
}
=== Côté Serveur ===
Du côté du serveur, nous avons volontairement choisi d'utiliser un format d'échange standard pour les communications. En effet, nous aurions pu simplement renvoyer le message "ip_client:port_client écrit :'Hello World'". Toutefois, nous ne maîtrisons pas toujours qui utilise nos services. Fort de ce constat, nous préférons utiliser des objets sérialisés en JSON.
public function onData($data, $client) {
foreach ($this->clients as $sendto) {
$obj = (object) null;
$obj->who = $client->toString();
$obj->msg = $data;
$sendto->send(json_encode($obj));
}
}
==== 4 - IRC (all browser compliant) ====
[[http://poulpe.heig-vd.ch/masrad/websockets/4-irc/|Lien sur l'application]]
Vouloir utiliser les web sockets pourrait, à plus ou moins long terme, devenir très intéressant. En attendant que tous les navigateurs acceptent et s'accordent sur l'API (et plus généralement sur toutes les APIs d'HTML5), il est nécessaire trouver des solutions afin de faire fonctionner les sockets d'une manière plus universelle.
Tout d'abord, on profitera de l'occasion, pour également intégrer la classe JSON qui n'est pas native sur certain browser.
En ce qui concerne les websockets, la solution qui convient le mieux pour les websockets est l'utilisation d'un composant flash. [[http://gimite.net/en/|Hiroshi Ichikawa]] avec son projet [[https://github.com/gimite/web-socket-js]] propose une librarie toute faite qui ne demande qu'une modification mineur du code pour rendre fonctionnel l'objet websocket. On notera par contre, un léger délai sur la réception des données pour les browsers utilisant le composant flash.
Solution : {{:ajax:4-irc-crossbrowser.zip|}}
===== Les exercices =====
==== Hash me! ====
En se basant sur l'exemple 1 et en modifiant {{:ajax:ex-hash-template.zip|}}, faire en sorte que le client envoie une chaine de caractères au serveur. Celui-ci lui renverra le hash md5 de la valeur au client qui l'affichera.
Solution : {{:ajax:ex-hash-solution.zip|}}
==== IRC++ ====
En partant de {{:ajax:ex-irc-template.zip|}} et de l'exemple 3, faire en sorte que :
* Les clients ne reçoivent pas leurs propres message. Il sera toutefois affiché sur l'interface par le javascript.
* Les clients peuvent mettre à jour leur nom d'utilisateur. Celui-ci sera transmis dans la liste des utilisateurs
* Les clients reçoivent et mettent à jour la liste des personnes connectées uniquement lorsque cela est nécessaire
Solution: {{:ajax:ex-irc-solution.zip|}}
===== Docs, Démo, etc... =====
* http://www.html5rocks.com/ présente beaucoup d'informations à propos de html5 et de toutes ces APIs
* http://dev.w3.org/html5/websockets/ Draft de l'API WebSocket