CLOUD COMPUTING.
DESARROLLO DE APLICACIONESY
MINERÍA WEB
Programa de extensión universitariaUniversidad de Oviedo
Miguel Fernández Fernández
miguel@ThirdWay.es
Web enTiempo Real
XMPP, Websockets, et al.
¿Qué es XMPP?
Extensible Messaging and Presence Protocol
Envío de mensajes en tiempo real
Codificados en XML
Transportados sobreTCP y UDP (media)
antesJabber
http://xmpp.org
¿Por qué XMPP?
HTTP
Half-duplex
para la Web
stateless
¿Por qué XMPP?
HTTP
Half-duplex
c
s
normal polling (AJAX)
c
s
long polling (Comet)
para la Web
stateless
¿Por qué XMPP?
HTTP
Half-duplex
c
s
normal polling (AJAX)
c
s
long polling (Comet)
para la Web
stateless
XMPP
Full-duplex
stateful
¿Por qué XMPP?
HTTP
Half-duplex
c
s
normal polling (AJAX)
c
s
long polling (Comet)
para la Web
stateless
XMPP
Full-duplex
stateful
c
s
conexión persistente
Arquitectura XMPP
O’REILLY XMPP:The Definitive Guide
Arquitectura XMPP
Web (HTTP) Mail (SMTP)
XMPP
La red XMPP: Entidades
Servidores
Plugins
Componentes
Clientes
Servidores
Enrutan mensajes
Hablan con clientes y otros servidores
FOSS: Ejabberd, Openfire,Tigase
Clientes
Humanos y robots
Protocolo cliente-servidor
Componentes
Extienden la funcionalidad del servidor
Tienen su propia identidad y dirección
Se ejecutan fuera del mismo
Se comunican con un protocolo específico
Ejemplo típico: Multichat
Plugins
Mismo propósito que los componentes
También tienen identidad y dirección
No hay IPC mayor rendimiento
Direccionamiento en XMPP
JIDs: almenos uno por cada entidad
local@dom.ain/resource
it@miinterprete.appspotchat.com/adium
Bare JID
Full JID
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat">
<body>Tomamos algo?</body>
</message>
<presence type="unavailable"/>
</stream:stream>
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat">
<body>Tomamos algo?</body>
</message>
<presence type="unavailable"/>
</stream:stream>
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat">
<body>Tomamos algo?</body>
</message>
<presence type="unavailable"/>
</stream:stream>
Dame mis contactos
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat">
<body>Tomamos algo?</body>
</message>
<presence type="unavailable"/>
</stream:stream>
Dame mis contactos
Estoy online
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat">
<body>Tomamos algo?</body>
</message>
<presence type="unavailable"/>
</stream:stream>
Dame mis contactos
Estoy online
Dile a bar que si
tomamos algo
XMPP Stanzas
<stream:stream>
<iq type="get">
<query xmlns="jabber:iq:roster"/>
</iq>
<presence/>
<message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat">
<body>Tomamos algo?</body>
</message>
<presence type="unavailable"/>
</stream:stream>
Dame mis contactos
Estoy online
Dile a bar que si
tomamos algoYa no estoy disponible
Tiempo real en La Web
Acercando XMPP a la Web
Pre HTML 5
Comunicación basada en HTTP
Bidirectional-Streams over
synchronous HTTP
AJAX & Long Polling
AJAX & Long Polling
setInterval(function(){
// pedimos cada 500 milisegundos esperando cambio
$.ajax({ url: '/my/page', success: function(data){} });
}, 500);
function load(){
$.ajax({ url: '/my/page', success: function(){
// abrimos la conexión durante 20 segundos
}, complete: load, timeout: 20000 });
}
AJAX (muestreo frecuente) Comet (Long Polling)
Latencia (200ms/petición)
Muchas peticiones no recogeran cambios
Se genera mucho tráfico
Reducción dramática de latencia
Mucho más eficiente
BOSH, XMPP sobre HTTP
http://xmpp.org/extensions/xep-0206.html
Flujos bidireccionales sobre HTTP síncrono
Usa pares de petición-respuesta para simular
Requiere de un proxy que dirija los stanzas al servidor XMPP
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 483
<body xmpp:version='1.0'
authid='ServerStreamID'
xmlns='http://jabber.org/protocol/httpbind'
xmlns:xmpp='urn:xmpp:xbosh'
xmlns:stream='http://etherx.jabber.org/streams'>
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>SCRAM-SHA-1</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
</body>
HTML5 Websockets
HTML 5
WebSockets
To enableWeb applications to maintain bidirectional
communications with server-side processes, this
specification introduces theWebSocket interface.
Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties)
Webkit 333 (Safari 4, Chrome >4)Soportado en:
HTML5 Websockets
HTML 5
WebSockets
To enableWeb applications to maintain bidirectional
communications with server-side processes, this
specification introduces theWebSocket interface.
Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties)
Webkit 333 (Safari 4, Chrome >4)Soportado en:
c
s
conexión persistente
El contrato Websocket
[Constructor(in DOMString url, in optional DOMString protocols)]
[Constructor(in DOMString url, in optional DOMString[] protocols)]
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();
};
WebSocket implements EventTarget;
estado de
la conexión
Recepción de eventos
Envío de mensajes
ws://services.com/service
Web en tiempo real con
Websockets
Event Machine
http://rubyeventmachine.com/
Framework I/O dirigida por eventos
Corre sobre ruby
à-la node.js (javascript) y twisted (python)
Implementa el patrón Reactor
Muy útil para crear aplicaciones servidor
eventmachine (0.12.10)
eventmachine-websocket (0.1.0)
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new WebSocket(url);
this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");};
this.ws.onclose = function() { alert("socket cerrado"); };
this.ws.onopen = function() { alert("conectado..."); };
this.send=function(msg) {this.ws.send(msg);}
}
var ws;
$(document).ready(function(){
ws=new WebSocketAdapter("ws://localhost:8080/");
});
</script>
</head>
<body>
<form>
Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input>
<input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/>
</form>
<div id="msg"></div>
</body>
</html>
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new WebSocket(url);
this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");};
this.ws.onclose = function() { alert("socket cerrado"); };
this.ws.onopen = function() { alert("conectado..."); };
this.send=function(msg) {this.ws.send(msg);}
}
var ws;
$(document).ready(function(){
ws=new WebSocketAdapter("ws://localhost:8080/");
});
</script>
</head>
<body>
<form>
Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input>
<input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/>
</form>
<div id="msg"></div>
</body>
</html>
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new WebSocket(url);
this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");};
this.ws.onclose = function() { alert("socket cerrado"); };
this.ws.onopen = function() { alert("conectado..."); };
this.send=function(msg) {this.ws.send(msg);}
}
var ws;
$(document).ready(function(){
ws=new WebSocketAdapter("ws://localhost:8080/");
});
</script>
</head>
<body>
<form>
Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input>
<input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/>
</form>
<div id="msg"></div>
</body>
</html>
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new WebSocket(url);
this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");};
this.ws.onclose = function() { alert("socket cerrado"); };
this.ws.onopen = function() { alert("conectado..."); };
this.send=function(msg) {this.ws.send(msg);}
}
var ws;
$(document).ready(function(){
ws=new WebSocketAdapter("ws://localhost:8080/");
});
</script>
</head>
<body>
<form>
Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input>
<input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/>
</form>
<div id="msg"></div>
</body>
</html>
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new WebSocket(url);
this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");};
this.ws.onclose = function() { alert("socket cerrado"); };
this.ws.onopen = function() { alert("conectado..."); };
this.send=function(msg) {this.ws.send(msg);}
}
var ws;
$(document).ready(function(){
ws=new WebSocketAdapter("ws://localhost:8080/");
});
</script>
</head>
<body>
<form>
Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input>
<input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/>
</form>
<div id="msg"></div>
</body>
</html>
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new WebSocket(url);
this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");};
this.ws.onclose = function() { alert("socket cerrado"); };
this.ws.onopen = function() { alert("conectado..."); };
this.send=function(msg) {this.ws.send(msg);}
}
var ws;
$(document).ready(function(){
ws=new WebSocketAdapter("ws://localhost:8080/");
});
</script>
</head>
<body>
<form>
Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input>
<input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/>
</form>
<div id="msg"></div>
</body>
</html>
Nuestro cliente<html>
<head>
<script src='jquery.min.js'></script>
<script>
function WebSocketAdapter(url){
this.ws=new WebSocket(url);
this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");};
this.ws.onclose = function() { alert("socket cerrado"); };
this.ws.onopen = function() { alert("conectado..."); };
this.send=function(msg) {this.ws.send(msg);}
}
var ws;
$(document).ready(function(){
ws=new WebSocketAdapter("ws://localhost:8080/");
});
</script>
</head>
<body>
<form>
Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input>
<input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/>
</form>
<div id="msg"></div>
</body>
</html>
Echo (single client)
require 'rubygems'
require 'eventmachine-websocket'
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |con|
con.on_open { con.send "Cliente conectado"}
con.on_message { |msg| con.send msg.reverse }
con.on_close { puts "Cliente desconectado" }
end
Multichat en 23LOC
require 'rubygems'
require 'eventmachine-websocket'
connections=[]
indexes={}
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |con|
con.on_open do
indexes[con]=connections.size+1
con.send "<p class="highlight">Eres el cliente #{indexes[con]}<p>"
connections.each{ |c| c.send "<p class="highlight">El cliente #{indexes[con]} ha entrado en la sala<p>" }
connections << con
end
con.on_message do |msg|
connections.each{ |c| c.send "<p><span class="cliente">Cliente #{indexes[con]}:</span> #{msg}</p>" }
end
con.on_close do
c.send "<p class="highlight">Has abandonado la sala</p>"
connections.delete con
indexes.delete con
end
end
Conclusiones
• Hasta la aparición de HTML5, XMPP tenía unas expectativas
muy altas como alternativa a Comet.
• Sin embargo, se han cancelado muchos servicios XMPP para
el consumo de datos en tiempo real (Twitter firehose API)
• Websocket se presenta como una alternativa más simple y
elegante para la implementación de servicios Web de tiempo
real
• XMPP no pierde fuerza para mensajería instantánea
Bilbiografía
Gracias
CLOUD COMPUTING.
DESARROLLO DE APLICACIONESY
MINERÍA WEB
Programa de extensión universitariaUniversidad de Oviedo
Miguel Fernández Fernández
miguel@ThirdWay.es

Real time

  • 1.
    CLOUD COMPUTING. DESARROLLO DEAPLICACIONESY MINERÍA WEB Programa de extensión universitariaUniversidad de Oviedo Miguel Fernández Fernández miguel@ThirdWay.es
  • 2.
    Web enTiempo Real XMPP,Websockets, et al.
  • 3.
    ¿Qué es XMPP? ExtensibleMessaging and Presence Protocol Envío de mensajes en tiempo real Codificados en XML Transportados sobreTCP y UDP (media) antesJabber http://xmpp.org
  • 4.
  • 5.
    ¿Por qué XMPP? HTTP Half-duplex c s normalpolling (AJAX) c s long polling (Comet) para la Web stateless
  • 6.
    ¿Por qué XMPP? HTTP Half-duplex c s normalpolling (AJAX) c s long polling (Comet) para la Web stateless XMPP Full-duplex stateful
  • 7.
    ¿Por qué XMPP? HTTP Half-duplex c s normalpolling (AJAX) c s long polling (Comet) para la Web stateless XMPP Full-duplex stateful c s conexión persistente
  • 8.
  • 9.
  • 10.
    La red XMPP:Entidades Servidores Plugins Componentes Clientes
  • 11.
    Servidores Enrutan mensajes Hablan conclientes y otros servidores FOSS: Ejabberd, Openfire,Tigase
  • 12.
  • 13.
    Componentes Extienden la funcionalidaddel servidor Tienen su propia identidad y dirección Se ejecutan fuera del mismo Se comunican con un protocolo específico Ejemplo típico: Multichat
  • 14.
    Plugins Mismo propósito quelos componentes También tienen identidad y dirección No hay IPC mayor rendimiento
  • 15.
    Direccionamiento en XMPP JIDs:almenos uno por cada entidad local@dom.ain/resource it@miinterprete.appspotchat.com/adium Bare JID Full JID
  • 16.
    XMPP Stanzas <stream:stream> <iq type="get"> <queryxmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream>
  • 17.
    XMPP Stanzas <stream:stream> <iq type="get"> <queryxmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream>
  • 18.
    XMPP Stanzas <stream:stream> <iq type="get"> <queryxmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream> Dame mis contactos
  • 19.
    XMPP Stanzas <stream:stream> <iq type="get"> <queryxmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream> Dame mis contactos Estoy online
  • 20.
    XMPP Stanzas <stream:stream> <iq type="get"> <queryxmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream> Dame mis contactos Estoy online Dile a bar que si tomamos algo
  • 21.
    XMPP Stanzas <stream:stream> <iq type="get"> <queryxmlns="jabber:iq:roster"/> </iq> <presence/> <message to="bar@otherside.com" from="foo@oneside.com/adium" type="chat"> <body>Tomamos algo?</body> </message> <presence type="unavailable"/> </stream:stream> Dame mis contactos Estoy online Dile a bar que si tomamos algoYa no estoy disponible
  • 22.
  • 23.
    Acercando XMPP ala Web Pre HTML 5 Comunicación basada en HTTP Bidirectional-Streams over synchronous HTTP AJAX & Long Polling
  • 24.
    AJAX & LongPolling setInterval(function(){ // pedimos cada 500 milisegundos esperando cambio $.ajax({ url: '/my/page', success: function(data){} }); }, 500); function load(){ $.ajax({ url: '/my/page', success: function(){ // abrimos la conexión durante 20 segundos }, complete: load, timeout: 20000 }); } AJAX (muestreo frecuente) Comet (Long Polling) Latencia (200ms/petición) Muchas peticiones no recogeran cambios Se genera mucho tráfico Reducción dramática de latencia Mucho más eficiente
  • 25.
    BOSH, XMPP sobreHTTP http://xmpp.org/extensions/xep-0206.html Flujos bidireccionales sobre HTTP síncrono Usa pares de petición-respuesta para simular Requiere de un proxy que dirija los stanzas al servidor XMPP HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 483 <body xmpp:version='1.0' authid='ServerStreamID' xmlns='http://jabber.org/protocol/httpbind' xmlns:xmpp='urn:xmpp:xbosh' xmlns:stream='http://etherx.jabber.org/streams'> <stream:features> <mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> <mechanism>SCRAM-SHA-1</mechanism> <mechanism>PLAIN</mechanism> </mechanisms> </stream:features> </body>
  • 26.
    HTML5 Websockets HTML 5 WebSockets ToenableWeb applications to maintain bidirectional communications with server-side processes, this specification introduces theWebSocket interface. Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties) Webkit 333 (Safari 4, Chrome >4)Soportado en:
  • 27.
    HTML5 Websockets HTML 5 WebSockets ToenableWeb applications to maintain bidirectional communications with server-side processes, this specification introduces theWebSocket interface. Gecko 2.0b4 (24/08/2010) (Firefox 4 Nighties) Webkit 333 (Safari 4, Chrome >4)Soportado en: c s conexión persistente
  • 28.
    El contrato Websocket [Constructor(inDOMString url, in optional DOMString protocols)] [Constructor(in DOMString url, in optional DOMString[] protocols)] 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(); }; WebSocket implements EventTarget; estado de la conexión Recepción de eventos Envío de mensajes ws://services.com/service
  • 29.
    Web en tiemporeal con Websockets
  • 30.
    Event Machine http://rubyeventmachine.com/ Framework I/Odirigida por eventos Corre sobre ruby à-la node.js (javascript) y twisted (python) Implementa el patrón Reactor Muy útil para crear aplicaciones servidor eventmachine (0.12.10) eventmachine-websocket (0.1.0)
  • 31.
    Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> functionWebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body> </html>
  • 32.
    Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> functionWebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body> </html>
  • 33.
    Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> functionWebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body> </html>
  • 34.
    Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> functionWebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body> </html>
  • 35.
    Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> functionWebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body> </html>
  • 36.
    Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> functionWebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body> </html>
  • 37.
    Nuestro cliente<html> <head> <script src='jquery.min.js'></script> <script> functionWebSocketAdapter(url){ this.ws=new WebSocket(url); this.ws.onmessage = function(evt) {$("#msg").append("<p>"+evt.data+"</p>");}; this.ws.onclose = function() { alert("socket cerrado"); }; this.ws.onopen = function() { alert("conectado..."); }; this.send=function(msg) {this.ws.send(msg);} } var ws; $(document).ready(function(){ ws=new WebSocketAdapter("ws://localhost:8080/"); }); </script> </head> <body> <form> Enviar al servidor: <input id="texto" type="text" value="hola mundo!"></input> <input id="enviar" type="button" value="enviar" onclick="ws.send($('#texto').val())"/> </form> <div id="msg"></div> </body> </html>
  • 38.
    Echo (single client) require'rubygems' require 'eventmachine-websocket' EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |con| con.on_open { con.send "Cliente conectado"} con.on_message { |msg| con.send msg.reverse } con.on_close { puts "Cliente desconectado" } end
  • 39.
    Multichat en 23LOC require'rubygems' require 'eventmachine-websocket' connections=[] indexes={} EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |con| con.on_open do indexes[con]=connections.size+1 con.send "<p class="highlight">Eres el cliente #{indexes[con]}<p>" connections.each{ |c| c.send "<p class="highlight">El cliente #{indexes[con]} ha entrado en la sala<p>" } connections << con end con.on_message do |msg| connections.each{ |c| c.send "<p><span class="cliente">Cliente #{indexes[con]}:</span> #{msg}</p>" } end con.on_close do c.send "<p class="highlight">Has abandonado la sala</p>" connections.delete con indexes.delete con end end
  • 41.
    Conclusiones • Hasta laaparición de HTML5, XMPP tenía unas expectativas muy altas como alternativa a Comet. • Sin embargo, se han cancelado muchos servicios XMPP para el consumo de datos en tiempo real (Twitter firehose API) • Websocket se presenta como una alternativa más simple y elegante para la implementación de servicios Web de tiempo real • XMPP no pierde fuerza para mensajería instantánea
  • 42.
  • 43.
  • 44.
    CLOUD COMPUTING. DESARROLLO DEAPLICACIONESY MINERÍA WEB Programa de extensión universitariaUniversidad de Oviedo Miguel Fernández Fernández miguel@ThirdWay.es