Chat en tiempo real con Flask, Angular y Socket.io

Gabriel
3 min readMay 23, 2021

Recientemente empecé a hacer aplicaciones usando python. Dado que aún no me he familiarizado lo suficiente con las frameworks disponibles y que ya tiene tiempo que quería aprender ha hacer aplicaciones de tiempo real con socket.io, pensé que sería una buena idea intentar hacer un chat usando flask, Angular y socket.io para aprender.

Flask back-end + socket.io

socket.io es una librería que permite la comunicación entre el cliente y servidor a través de eventos. Para este simple chat decidí usar los siguientes tres eventos:

  1. El usuario se conecta
  2. El usuario se desconecta
  3. El usuario manda un mensaje

Aquí esta como se ve mi código para manejar los primeros dos eventos:

Cuando empecé a trabajar en este pequeño ejercicio tuve algunas dificultades con CORS (Cross-Origin Resource Sharing), hasta que me dí cuenta que debía especificar los permisos con SocketIO(app, cors_allowed_origins="*")además deCORS(app).

@socketio.on('sign_in') será ejecutado cada vez que un usuario se conecte. El cliente mandará un objeto con la propiedad “name” y el http request incluirá el “socket id” en request.id.

Para esta simple aplicación pensé que una de las maneras más sencillas de guardar la información de los usuarios sería usar un diccionario donde el socked id seria el key y el nombre de usuario el valor user[request.sid]=user_name['name'] . Una vez que un usuario se conecta, el evento current_users es activado y el diccionario con la información de todos los usuarios es reenviado a todos los clientes.

@socketio.on('disconnect') es ejecutado cuando un usuario se desconecta y borrara la información del usuario del diccionario con users.pop(request.sid,'No user found') (el “Not user found” es usado por conveniencia para que esta función no regrese un error si request.sid no existe en el diccionario). Una vez que el diccionario de usuarios se actualiza, este es emitido una vez más a todos los clientes usando el evento “current_users”.

Ya que tenemos un sistema para guardar la información de los usuarios, veamos como manejar el enviar y recibir mensajes:

Éste código recibe y emite mensajes. Aquí estoy aprovechando el hecho que por default, cada cliente se une a un cuarto de socket.io con su respectivo socket.id. Aquí estoy emitiendo mensajes a dos cuartos, el cuarto del destinatario (sender) y remitente (receiver). Esto implica que cada cliente va a recibir todos sus mensajes en el mismo cuarto (que tiene el mismo nombre que su socket.id), y por lo tanto manejaré como el usuario ve los mensajes recibidos por usuarios específicos directamente en el front-end.

Esto es lo único necesario para el back-end. El código completo se ve así:

Angular front-end

El front-end en Angular es algo extenso y complicado de describir completamente en un blog post. Brevemente, para este ejercicio usé dos servicios: El LoginService ( login.service.ts ) y un ChatService ( chat.service.ts ). El LoginService manejara la autenticación (i.e. el evento sign_in ):

La funciónlogin() emitirá el evento sign_in y enviará los detalles del usuario al servidor. A su vez, el servidor añadirá este nuevo usuario al diccionario de usuarios y le avisará a todos los clientes acerca de esta nueva conexión emitiendo el evento current_users (véase código del back-end).

Finalmente, el ChatService se encarga del resto de los eventos del chat:

La funcióngetUsers() regresa un observable al cual nos podemos subscribir y obtener la lista de los usuarios conectados. Esta será actualizada cada vez que alguien se conecte o desconecte. Similarmente, getMessage() nos permite hacer el seguimiento de los mensajes enviados al cliente, y senMessage() emitirá el evento ‘message’ que enviará el mensaje, junto con el socket.id del usuario que lo debe recibir y de quién lo envía.

El producto final es un muy simple chat de tiempo real y una buena experiencia de aprendizaje para mí.

El código completo de la aplicación esta aquí.

--

--