Introducción a Socket.io #nodejs
Para seguir esta introducción necesitas tener Node.js y Express.js
Antes de nada describamos socket.io
Socket.io es una librería que nos permite manejar eventos en tiempo real mediante una conexión TCP y todo ello en JavaScript. Es realmente potente y podemos hacer todo tipo de aplicaciones en tiempo real. Hay muchos ejemplos de chat (que puede ser lo más llamativo) por ahí. Pero yo quiero hacer algo mucho más sencillo, para que comprender su funcionamiento lleve el menor tiempo posible.
- Añadiendo socket.io al proyecto:
Si tenemos instalado Express.js ejecutamos el comando
express socketexample
y nos creará un directorio con un proyecto básico que podemos ejecutar entrando en el directorio cd socketexample
y ejecutándolo node app.js
Ya tenemos nuestro proyecto express, ahora vamos a instalar Socket.io con
npm install socket.io
.
Antes de importarlo en nuestro proyecto necesitamos ajustar un poco el archivo app.js que nos ha creado express para hacer que socket.io escuche en el mismo puerto que lo hace express, para eso guardamos el servidor así:
var server = http.createServer(app).listen(app.get('port'), function(){ console.log("Express server listening on port " + app.get('port')); });
Y ahora sí importamos socket.io y lo iniciamos con `var io = require(‘socket.io’).listen(server);“
Debe quedar así:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| /** * Module dependencies. */ var express = require( 'express' ) , routes = require( './routes' ) , http = require( 'http' ); var app = express(); app.configure( function (){ app.set( 'port' , process.env.PORT || 3000); app.set( 'views' , __dirname + '/views' ); app.set( 'view engine' , 'jade' ); app.use(express.favicon()); app.use(express.logger( 'dev' )); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(__dirname + '/public' )); }); app.configure( 'development' , function (){ app.use(express.errorHandler()); }); app.get( '/' , routes.index); var server = http.createServer(app).listen(app.get( 'port' ), function (){ console.log( "Express server listening on port " + app.get( 'port' )); }); var io = require( 'socket.io' ).listen(server); |
Ya sí que tenemos el proyecto preparado para usar socket.io por parte del servidor.
- Usando socket.io en el servidor y cliente.
Ya tenemos socket.io en el proyecto, vamos a usarlo en el servidor y en el cliente.
Para usar socket.io en el servidor debemos usar el objeto io. Socket.io se basa en eventos, pero para manejar estos eventos primero debemos crear una conexión entre el servidor y el cliente con el siguiente código:
io.sockets.on('connection', callback(socket));
Este socket maneja la conexión cliente-servidor y nos ofrece las dos propiedades con las que vamos a trabajar, on (escucha eventos) y emit (emite eventos), aunque haya más como broadcast, set, of, volatile para temas más concretos.
Empecemos:
1
2
3
4
| io.sockets.on( 'connection' , function (socket){ socket.emit( 'connected' ); //Evento creado por nosotros se puede llamar 'pepito' }); |
Con
socket.emit('connected');
emitimos un evento creado por nosotros, lo he llamado así porque creo que es el mejor nombre para decirle al cliente que estamos conectados.
Por ahora es suficiente para mostrar el mensaje de conectado.
Ahora, vamos a ver qué ponemos en el cliente, vamos a editar el archivo
layout.jade
para importar la librería socket.io que automáticamente sirve nuestro servidor en la ruta/socket.io/socket.io.js
para ello la importamos en el head. Recordad que estamos usando Jade y debe hacerse así script(src='/socket.io/socket.io.js')
Después vamos a usarla al final de la vista
index.jade
, puesto que vamos a tratar con ella.
Nuestro propósito es que aparezca un mensaje que indique que estás conectado y después, que en tiempo real, pulsando un botón emita otro evento y el servidor indique el número de eventos que se ha recibido.
Primero vamos a hacer la lógica de conexión y desconexión, para ello he creado los dos mensajes, ocultando el de conectado y mostrando por defecto el de desconectado.
Veamos como va por ahora el código en el cliente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| extends layout block content h1= title #disconected p Desconectado! #connected.hide p Conectado! input(type= 'button' , value= 'Enviar pulsación' ) script //#1 Declaramos el objeto socket que se conectará en este caso a localhost //#2 Función que muestra un mensaje u otro, dependiendo de la conexión. function toggle(){ $( "#disconected" ).toggleClass( "hide" ); $( "#connected" ).toggleClass( "hide" ); } //#3 Si estamos conectados, muestra el log y cambia el mensaje socket.on( 'connected' , function () { console.log( 'Conectado!' ); toggle(); }); //#4 Si nos desconectamos, muestra el log y cambia el mensaje. socket.on( 'disconnect' , function () { console.log( 'Desconectado!' ); toggle(); }); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| body { padding: 50px; font: 14px "Lucida Grande" , Helvetica, Arial, sans-serif; } a { color: #00B7FF; } #disconected p { color: red; background-color: rgba(200, 0, 0, 0.4); } #connected p { color: green; background-color: rgba(0,200,0,0.4); } .hide { display: none; } |
- #1
Una vez hemos declarado el objeto socket, con el podemos recibir eventos con
socket.on('evento', callback);
y emitirlos con socket.emit('evento', data);
- #2
Una simple función que usa jquery para mostrar u ocultar el mensaje de conectado o desconectado.
- 3#
Escuchamos continuamente hasta que recibamos el evento creado por nosotros en el servidorserver.js y una vez recibido en el callback llamamos a la función creada en el punto 2 para cambiar el mensaje.
- 4#
Permanece escuchando hasta que se desconecte, una vez desconectado volvemos a cambiar el mensaje indicando que estamos desconectados.
Si ejecutas el proyecto ahora y accedes a localhost:3000, verás que el mensaje aparece en verde. Corta el servidor con Ctrl+C y verás que el mensaje ha cambiado a desconectado. Vuelve a encenderlo sin recargar la página y comprueba que vuelve a verde.
- Emitiendo eventos desde el cliente al servidor y contestar con datos
Ahora vamos a poner el botón que emitirá el evento, he utilizado un simple
imput(type='button', value='Enviar click')#click
con la id click para capturar con jquery cuando se pulsa el elemento con esa id.
Al pulsarlo llamamos a
socket.emit('click');
con jQuery y el servidor nos responderá con el evento otherClick.
Mejor veamos el código del cliente y del servidor.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| /** * Module dependencies. */ var express = require( 'express' ) , routes = require( './routes' ) , http = require( 'http' ); var app = express(); app.configure( function (){ app.set( 'port' , process.env.PORT || 3000); app.set( 'views' , __dirname + '/views' ); app.set( 'view engine' , 'jade' ); app.use(express.favicon()); app.use(express.logger( 'dev' )); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(__dirname + '/public' )); }); app.configure( 'development' , function (){ app.use(express.errorHandler()); }); //Declaramos una variable con el número de clicks. var clicks = 0; app.get( '/' , routes.index); //Asignamos a server la creación del servidor http. var server = http.createServer(app).listen(app.get( 'port' ), function (){ console.log( "Express server listening on port " + app.get( 'port' )); }); //Importamos socket.io utilizando el servidor creado anteriormente. var io = require( 'socket.io' ).listen(server); //Iniciamos la conexión. io.sockets.on( 'connection' , function (socket){ //Emitimos nuestro evento connected socket.emit( 'connected' ); //Permanecemos a la escucha del evento click socket.on( 'click' , function (){ //Sumamos el click clicks++; //Emitimos el evento que dirá al cliente que hemos recibido el click //y el número de clicks que llevamos socket.emit( 'otherClick' , clicks); }); }); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| extends layout block content h1= title #disconected p Desconectado! #connected.hide p Conectado! h2 Has pulsado 0 veces! input(type= 'button' , value= 'Enviar pulsación' ) #button script //#1 Declaramos el objeto socket que se conectará en este caso a localhost //#2 Función que muestra un mensaje u otro, dependiendo de la conexión. function toggle(){ $( "#disconected" ).toggleClass( "hide" ); $( "#connected" ).toggleClass( "hide" ); } //#3 Si estamos conectados, muestra el log y cambia el mensaje socket.on( 'connected' , function () { console.log( 'Conectado!' ); toggle(); }); //#4 Si pulsas el botón, envía el evento click $( '#button' ).click( function (){ socket.emit( 'click' ); }); //#5 El servidor nos responde al click con este evento y nos da el número de clicks en el callback. socket.on( 'otherClick' , function (clicks){ console.log( 'Clicks: ' +clicks); $( 'h2' ).replaceWith( '<h2>Has pulsado ' +clicks+ ' veces!' ); }); //#6 Si nos desconectamos, muestra el log y cambia el mensaje. socket.on( 'disconnect' , function () { console.log( 'Desconectado!' ); toggle(); }); |
En el servidor escuchamos el evento click, en el callback del evento sumamos un click a la variable y emitimos que hemos recibido un click y mandamos junto al evento el número de clicks.
En el cliente recibimos el evento otherClick y el número de clicks en el callback y los mostramos haciendo uso de jQuery.
Ejecutamos el servidor y vemos el funcionamiento.
- Por último…
Si quieres, puedes poner un log en el callback del evento click en el server y comprobar que al pulsar el botón en el server se imprime.
Dejo el código en Github del proyecto completo y os animo a que añadáis mejoras para aprender a usar Socket.io con la práctica.
Autor de éste Artículo
Francisco López (@donflopez), webapp developer. Especializado en Node.js, Express.js, MongoDB y Socket.io. Localizable en Github,Twitter o en el blog donde actualmente escribe Tumblr.
Oscar perez
0 comentarios:
Publicar un comentario