Ejemplos de Websocket de Node.js con Socket.io

    驴Qu茅 son los Websockets?

    En los 煤ltimos a帽os, un nuevo tipo de comunicaci贸n comenz贸 a surgir en la web y en las aplicaciones m贸viles, llamado websockets. Este protocolo ha sido esperado durante mucho tiempo y finalmente fue estandarizado por la IETF en 2011, allanando el camino para un uso generalizado.

    Este nuevo protocolo abre una l铆nea de comunicaci贸n con el cliente mucho m谩s r谩pida y eficiente. Al igual que HTTP, los websockets se ejecutan sobre una conexi贸n TCP, pero son mucho m谩s r谩pidos porque no tenemos que abrir una nueva conexi贸n cada vez que queremos enviar un mensaje, ya que la conexi贸n se mantiene activa mientras el servidor o el cliente quiere.

    A煤n mejor, dado que la conexi贸n nunca termina, finalmente tenemos comunicaci贸n full-duplex disponible, lo que significa que podemos enviar datos al cliente en lugar de tener que esperar a que soliciten datos del servidor. Esto permite que los datos se comuniquen de un lado a otro, lo que es ideal para cosas como aplicaciones de chat en tiempo real o incluso juegos.

    驴C贸mo funcionan los Websockets?

    En esencia, un websocket es solo una conexi贸n TCP que permite la comunicaci贸n full-duplex, lo que significa que cualquier lado de la conexi贸n puede enviar datos al otro, incluso al mismo tiempo.

    Para establecer esta conexi贸n, el protocolo en realidad inicia el protocolo de enlace como una solicitud HTTP normal, pero luego se ‘actualiza’ usando el solicitud de actualizaci贸n Encabezado HTTP, como este:

    GET /ws/chat HTTP/1.1
    Host: chat.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: q1PZLMeDL4EwLkw4GGhADm==
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 15
    Origin: http://example.com
    

    Luego, el servidor env铆a una respuesta HTTP 101 “Protocolos de conmutaci贸n”, reconociendo que la conexi贸n se actualizar谩. Una vez realizada esta conexi贸n, cambia a un protocolo binario bidireccional, momento en el que se pueden enviar los datos de la aplicaci贸n.

    Todo lo que tiene que hacer el protocolo para mantener la conexi贸n abierta es enviar algunos paquetes de ping / pong, lo que le dice al otro lado que todav铆a est谩n all铆. Para cerrar la conexi贸n, se env铆a un paquete simple de “cerrar conexi贸n”.

    Algunos ejemplos de Websocket

    De las muchas bibliotecas websocket diferentes para Node.js disponibles para nosotros, eleg铆 usar socket.io a lo largo de este art铆culo porque parece ser el m谩s popular y, en mi opini贸n, el m谩s f谩cil de usar. Si bien cada biblioteca tiene su propia API 煤nica, tambi茅n tienen muchas similitudes, ya que todas est谩n construidas sobre el mismo protocolo, por lo que es de esperar que pueda traducir el c贸digo a continuaci贸n a cualquier biblioteca que desee usar.

    Para el servidor HTTP, usar茅 R谩pido, que es el servidor de node m谩s popular que existe. Tenga en cuenta que tambi茅n puede usar el simple http m贸dulo si no necesita todas las funciones de Express. Aunque, dado que la mayor铆a de las aplicaciones usar谩n Express, eso es lo que usaremos tambi茅n.

    Nota: A lo largo de estos ejemplos, he eliminado gran parte del c贸digo est谩ndar, por lo que parte de este c贸digo no funcionar谩 de inmediato. En la mayor铆a de los casos, puede consultar el primer ejemplo para obtener el c贸digo est谩ndar.

    Establecer la conexi贸n

    Para que se establezca una conexi贸n entre el cliente y el servidor, el servidor debe hacer dos cosas:

    • Con茅ctese al servidor HTTP para manejar las conexiones websocket
    • Sirva el socket.io.js biblioteca cliente como recurso est谩tico

    En el siguiente c贸digo, puede ver que el elemento (1) se realiza en la tercera l铆nea. El elemento (2) est谩 hecho para usted (por defecto) por el socket.io biblioteca y se sirve en el camino /socket.io/socket.io.js. De forma predeterminada, todas las conexiones y recursos de websocket se sirven dentro del /socket.io camino.

    Servidor

    var app = require('express')();
    var server = require('http').Server(app);
    var io = require('socket.io')(server);
    
    app.get("https://Pharos.sh.com/", function(req, res) {
        res.sendFile(__dirname + '/index.html');
    });
    
    server.listen(8080);
    

    El cliente tambi茅n debe hacer dos cosas:

    • Cargue la biblioteca desde el servidor
    • Llamada .connect() a la direcci贸n del servidor y la ruta de websocket

    Cliente

    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io.connect("https://Pharos.sh.com/");
    </script>
    

    Si navega con su navegador a http://localhost:8080 e inspeccionar las solicitudes HTTP detr谩s de escena utilizando las herramientas de desarrollo de su navegador, deber铆a poder ver el protocolo de enlace que se est谩 ejecutando, incluidas las solicitudes GET y la respuesta resultante de los protocolos de conmutaci贸n HTTP 101.

    Env铆o de datos del servidor al cliente

    Bien, ahora pasemos a algunas de las partes m谩s interesantes. En este ejemplo, le mostraremos la forma m谩s com煤n de enviar datos desde el servidor al cliente. En este caso, enviaremos un mensaje a un canal, al que el cliente puede suscribirse y recibir. Entonces, por ejemplo, una aplicaci贸n cliente podr铆a estar escuchando en el canal de ‘anuncios’, que contendr铆a notificaciones sobre eventos en todo el sistema, como cuando un usuario se une a una sala de chat.

    En el servidor, esto se hace esperando a que se establezca la nueva conexi贸n, luego llamando al socket.emit() m茅todo para enviar un mensaje a todos los clientes conectados.

    Servidor

    io.on('connection', function(socket) {
        socket.emit('announcements', { message: 'A new user has joined!' });
    });
    

    Cliente

    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io.connect("https://Pharos.sh.com/");
        socket.on('announcements', function(data) {
            console.log('Got announcement:', data.message);
        });
    </script>
    

    Env铆o de datos de cliente a servidor

    Pero, 驴qu茅 har铆amos cuando queramos enviar datos al rev茅s, de cliente a servidor? Es muy similar al 煤ltimo ejemplo, utilizando tanto el socket.emit() y socket.on() m茅todos.

    Servidor

    io.on('connection', function(socket) {
        socket.on('event', function(data) {
            console.log('A client sent us this dumb message:', data.message);
        });
    });
    

    Cliente

    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io.connect("https://Pharos.sh.com/");
        socket.emit('event', { message: 'Hey, I have an important message!' });
    </script>
    

    Contando usuarios conectados

    Este es un buen ejemplo para aprender, ya que muestra algunas caracter铆sticas m谩s de socket.io (como el disconnect event), es f谩cil de implementar y es aplicable a muchas aplicaciones web. Usaremos el connection y disconnect eventos para contar el n煤mero de usuarios activos en nuestro sitio, y actualizaremos a todos los usuarios con el recuento actual.

    Servidor

    var numClients = 0;
    
    io.on('connection', function(socket) {
        numClients++;
        io.emit('stats', { numClients: numClients });
    
        console.log('Connected clients:', numClients);
    
        socket.on('disconnect', function() {
            numClients--;
            io.emit('stats', { numClients: numClients });
    
            console.log('Connected clients:', numClients);
        });
    });
    

    Cliente

    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io.connect("https://Pharos.sh.com/");
        socket.on('stats', function(data) {
            console.log('Connected clients:', data.numClients);
        });
    </script>
    

    Una forma mucho m谩s simple de rastrear el n煤mero de usuarios en el servidor ser铆a simplemente usar esto:

    var numClients = io.sockets.clients().length;
    

    Pero aparentemente hay algunos asuntos en torno a esto, por lo que es posible que tenga que realizar un seguimiento del recuento de clientes usted mismo.

    Salas y espacios de nombres

    Lo m谩s probable es que a medida que su aplicaci贸n crezca en complejidad, necesitar谩 m谩s personalizaci贸n con sus websockets, como enviar mensajes a un usuario espec铆fico o conjunto de usuarios. O tal vez desee necesitar una estricta separaci贸n de la l贸gica entre las diferentes partes de su aplicaci贸n. Aqu铆 es donde entran en juego las habitaciones y los espacios de nombres.

    Nota: Estas funciones no forman parte del protocolo websocket, pero se agregan socket.io.

    Por defecto, socket.io usa el espacio de nombres ra铆z (/) para enviar y recibir datos. Mediante programaci贸n, puede acceder a este espacio de nombres a trav茅s de io.sockets, aunque muchos de sus m茅todos tienen atajos en io. Entonces estas dos llamadas son equivalentes:

    io.sockets.emit('stats', { data: 'some data' });
    io.emit('stats', { data: 'some data' });
    

    Para crear su propio espacio de nombres, todo lo que tiene que hacer es lo siguiente:

    var iosa = io.of('/Pharos.sh');
    iosa.on('connection', function(socket){
        console.log('Connected to Stack Abuse namespace'):
    });
    iosa.emit('stats', { data: 'some data' });
    

    Adem谩s, el cliente debe conectarse a su espacio de nombres expl铆citamente:

    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io('/Pharos.sh');
    </script>
    

    Ahora cualquier dato enviado dentro de este espacio de nombres estar谩 separado del predeterminado / espacio de nombres, independientemente del canal que se utilice.

    Yendo a煤n m谩s lejos, dentro de cada espacio de nombres puede unirse y salir de ‘salas’. Estas salas proporcionan otra capa de separaci贸n en la parte superior de los espacios de nombres y, dado que un cliente solo se puede agregar a una sala en el lado del servidor, tambi茅n brindan cierta seguridad adicional. Entonces, si desea asegurarse de que los usuarios no est茅n fisgoneando en ciertos datos, puede usar una sala para ocultarlos.

    Para ser agregado a una habitaci贸n, debe .join() eso:

    io.on('connection', function(socket){
        socket.join('private-message-room');
    });
    

    Luego, desde all铆, puede enviar mensajes a todos los que pertenecen a la sala determinada:

    io.to('private-message-room').emit('some event');
    

    Y finalmente, llama .leave() para dejar de recibir mensajes de eventos de una sala:

    socket.leave('private-message-room');
    

    Conclusi贸n

    Esta es solo una biblioteca que implementa el protocolo websockets, y hay muchas m谩s, todas con sus propias caracter铆sticas y fortalezas 煤nicas. Aconsejar铆a probar algunos de los otros (como node-websockets) para que tengas una idea de lo que hay ah铆 fuera.

    En solo unas pocas l铆neas, puede crear algunas aplicaciones bastante poderosas, 隆as铆 que tengo curiosidad por ver qu茅 se le ocurre!

    驴Tiene algunas ideas interesantes o ya ha creado algunas aplicaciones con websockets? 隆H谩znoslo saber en los comentarios!

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *