Cómo usar Flask-SocketIO para crear aplicaciones en tiempo real (WebSockets) con Python
Índice de contenido
- ¿Qué es Flask-SocketIO y para qué sirve?
- Diferencias entre HTTP y WebSocket
- Instalación y configuración inicial
- ⚙️ Configuración del servidor de sockets
- Cómo funciona Flask-SocketIO
- Eventos, emit y escucha
- Crear nuestro Room
- Conectarse y desconectarse
- Unirnos y abandonar rooms
- Crear un chat en tiempo real con Flask-SocketIO
- ️ Servidor: manejar eventos y mensajes
- Cliente: emitir y recibir mensajes
- Servidor
- Ejemplo completo paso a paso
- Autenticación con Flask-Login
- Controlar quién ve qué mensajes
- ⚙️ Buenas prácticas y despliegue en producción
- Eventlet y Gunicorn
- Seguridad y manejo de sesiones
- Escalabilidad y monitoreo
- Conclusión
- ❓ Preguntas frecuentes (FAQs)
Flask-SocketIO es una extensión de Flask que permite la integración de WebSockets en una aplicación Flask, lo que permite la comunicación bidireccional en tiempo real entre el servidor y el cliente sin necesidad de actualizar constantemente la página; por ejemplo, en una app tipo chat, tu envías el mensaje al servidor, a otra persona o grupo de personas; pero, también puede recibir mensajes, por lo tanto, en el esquema clásico de cliente servidor no es posible obtener el mensaje de la misma manera que los envías.
Por lo tanto tendrías que estar recargando o enviando peticiones al servidor cada ciertos cambios para consultar si tienes posibles mensajes, pero, en la comunicación full duplex existe un canal entre el servidor al cliente (la inversa) y no hay necesidad de enviar peticiones al servidor cada cierto tiempo (que es un enfoque ineficiente).
Si alguna vez quisiste enviar y recibir mensajes sin tener que recargar la página, Flask-SocketIO es tu herramienta ideal. Esta extensión de Flask permite añadir comunicación en tiempo real (full-duplex) a tus proyectos de Python con una facilidad sorprendente.
Cuando desarrollé un sistema de chat con Flask, me di cuenta de que HTTP tradicional no bastaba: necesitaba un canal activo entre el servidor y el cliente que me permitiera enviar datos de inmediato. Ahí entró Flask-SocketIO.
Quedamos en que sabemos Cómo implementar el control de acceso basado en roles en Flask
¿Qué es Flask-SocketIO y para qué sirve?
Flask-SocketIO es una extensión que integra WebSockets dentro de un proyecto Flask, permitiendo una comunicación bidireccional permanente entre el servidor y los navegadores.
Flask-SocketIO utiliza una implementación de WebSocket de la biblioteca Socket.IO de JavaScript, que es compatible con múltiples navegadores y admite la creación de salas para manejar múltiples conexiones simultáneas. Además, proporciona funciones para enviar mensajes al cliente y recibir mensajes del cliente en tiempo real.
La comunicación entre clientes y servidores es parte de cualquier aplicación disponible hoy en día que se encuentre en Internet. Los sockets web son un protocolo desarrollado para facilitar este proceso. Nos permiten establecer un contacto bidireccional entre un cliente (o varios clientes) y un servidor. Puede pensar en su navegador web como un cliente, por ejemplo. El servidor puede ser un programa de fondo que se ejecuta en su sistema.
WebSocket es un protocolo de comunicación para el modelo cliente-servidor; para comprender WebSocket, es mejor comparar la especialidad de WebSocket sobre HTTPS.

Hay algunas ventajas de WebSocket sobre HTTPS, pero pasan sobre todo por la posibilidad de crear un canal fullduplex entre el cliente y servidor, y la posibilidad de crear habitaciones para alojar clientes, crear broadcast entre otros.
El uso de los Websoket es muy facil en Flask, al igual que ocurre con otras posibles dependencias, podemos instalar un plugin con el cual tener el completo control de los webSokect en Flask y la habilitación de un servidor especial para poder utilizar los websokect.
En esta entrada, veremos como podemos crear habitaciones para comunicar varios clientes entre si, con mensajes al servidor y viseversa.
Diferencias entre HTTP y WebSocket
HTTP sigue el patrón clásico: el cliente pide y el servidor responde.
WebSocket, en cambio, mantiene un canal abierto que permite que el servidor también envíe datos sin esperar una solicitud.
En mi experiencia, esto cambia completamente el flujo de una app: cuando un usuario envía un mensaje, los demás lo reciben en tiempo real, sin recargar ni consultar cada segundo.
⚡ Ventajas de la comunicación full-duplex
- Actualizaciones instantáneas de datos.
- Menor carga en el servidor (sin polling constante).
- Ideal para chats, dashboards, juegos, streaming o notificaciones.
Instalación y configuración inicial
️ Crear entorno virtual e instalar Flask-SocketIO
Como siempre, recomiendo trabajar en un entorno aislado en un ambiente virtual para Flask:
$ python3 -m venv flask_socket_env
$ source flask_socket_env/bin/activate
$ pip install flask flask-socketio️ Estructura base del proyecto
/flask_socket_app
│
├── app.py
└── templates/
└── index.html
⚙️ Configuración del servidor de sockets
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'clave_secreta_segura'
socketio = SocketIO(app)
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
socketio.run(app, debug=True)Cómo funciona Flask-SocketIO
Eventos, emit y escucha
Flask-SocketIO funciona a través de eventos: el servidor escucha y el cliente emite.
Por ejemplo:
@socketio.on('mensaje')
def handle_message(data):
print('Mensaje recibido:', data)
socketio.emit('mensaje', data)Crear nuestro Room
El uso de los rooms es un mecanismo que nos permite tener mayor control sobre los usuarios que se puedan conectar a nuestros canales dúplex desde el cliente y el servidor; a diferencia de la comunicación que tenemos en Flask SocketIO en la cual no tenemos este control, ya que cualquier usuario que entra al apartado de nuestra web en la que habilitamos los socket, como mostramos el video de la portada. Podrá tener acceso total a los mismos sin control algunos; pero con los rooms ahora podemos indicar que usuario va a unirse o abandonar una sala; esto nos da mucho más control sobre qué usuario puede o no acceder a ver los mensajes que compartimos por dicha habitación; para esto, colocamos un parámetro más a comunicación tanto en el servidor como en el cliente al emitir los eventos:
emit('chat', message['message'], broadcast=True, to=message['room'])
socket.emit('chat', { message: message.value.trim(), room:"room{{current_user.id}}"})Conectarse y desconectarse
En Flask Socket IO, podemos detectar fácilmente cuando nos conectamos y desconectamos del servidor de socket; para eso:
@socketio.on('connect')
def connect():
print("Conectado!!!!!!!")
@socketio.on('disconnect')
def disconnect():Unirnos y abandonar rooms
Por lo tanto, ahora vamos a usar dos funciones más para poder unirnos a una habitación o abandonar la misma.
Para unirnos a una habitación:
join_room Y para salirnos de una habitación:
leave_roomCrear un chat en tiempo real con Flask-SocketIO
️ Servidor: manejar eventos y mensajes
La función de chat, que empleamos para enviar mensajes desde el servidor; es decir, Flask:
@socketio.on('chat')
def chat(message):
print("Chat:", message)
socketio.emit('chat', message['message'], broadcast=True, to=message['room'])En esta función emitimos un evento, pasado desde el cliente y con el broadcast indicamos que todos los clientes que se encuentren escuchando la habitación de message['room'] recibirán este mensaje; esta función es usada desde el cliente como veremos en unos momentos.
Cliente: emitir y recibir mensajes
Y desde el cliente, es decir, JavaScript:
<textarea id="message"></textarea>
<button onclick="sendMsg()">Enviar</button>
<script>
const socket = io();
function sendMsg() {
const message = document.querySelector("#message").value.trim();
if (!message) return alert("No hay mensaje que enviar");
socket.emit('chat', { message: message, room: "room1" });
}
socket.on('chat', msg => console.log("Nuevo mensaje:", msg));
</script>En esta función hacemos las verificaciones típicas para saber si tenemos datos, luego de esto, mediante la función de emit, emitimos el evento a la función de chat alojada en el servidor, la que vimos anteriormente.
Servidor
Volviendo al servidor, es importante notar que, pasa usar un socket, necesitamos unirnos y tambien poder dejar ese grupo; como comentamos antes, para eso existen las funciones de join_room y leave_room, en las cuales, con la sesión habilitada, nos unimos o dejamos el grupo respectivamente.
Finalmente, las funciones para unirnos o salirnos del grupo que usamos:
@socketio.on('join')
def join(room):
username=current_user.name
print("Join")
join_room(room['room'])
emit('join', username+" se unio a la habitacion", to=room['room'])
@socketio.on('leave')
def leave(room):
username=current_user.name
print("leave")
leave_room(room['room'])
emit('leave', username+" abandono la habitacion", to=room['room'])Como puedes ver, para hacerlo un poco más interesante, empleamos Flask Login para tener datos diferentes para cada usuario que realice una conexión.
El parámetro room lo puedes tomar de cualquier parte, una referencia que venga desde la vista, base de datos, etc; en este ejemplo lo tenemos establecido por defecto desde la función chat del cliente.
Ya con esto, podemos enviar mensajes que solamente van a escuchar los usuarios que se encuentren asignada tras previo acceso a la habitación llamada "room"; para eso tenemos un par de botones:
<button onclick="join()">Unir</button>
<button onclick="leave()">Abandonar</button>Y sus correspondientes funciones:
function join(){
socket.emit('join', { room:"room{{current_user.id}}"})
}
function leave(){
socket.emit('leave', { room:"room{{current_user.id}}"})
}Ejemplo completo paso a paso
Estas implementaciones, es ideal para aplicaciones tipo chat o colaboración en vivo.
Finalmente, te dejo el código completo que forma parte de mi curso completo de Flask con Python (link abajo):
from flask import Blueprint,render_template
from flask_socketio import emit, join_room, leave_room
from flask_login import login_required, current_user
from app import db, socketio
from app.user.models import User
from app.chat.models import MessageRoom
from datetime import datetime
roomBp = Blueprint('room',__name__)
@roomBp.route("/room")
@login_required
def index():
return render_template("room/index.html")
@socketio.on('chat')
@login_required
def chat(message):
print("Estamos en evento "+str(message))
emit('chat', message['message'], broadcast=True, to=message['room'])
@socketio.on('join')
@login_required
def join(room):
username=current_user.name
print("Join")
join_room(room['room'])
emit('join', username+" se unio a la habitacion", to=room['room'])
@socketio.on('leave')
@login_required
def leave(room):
username=current_user.name
print("leave")
leave_room(room['room'])
emit('leave', username+" se unio a la habitacion", to=room['room'])Autenticación con Flask-Login
Usé Flask-Login para usuarios autenticados pudieran unirse a salas.
Esto añade una capa real de seguridad al chat, algo que muchas guías omiten.
Controlar quién ve qué mensajes
Al usar rooms, puedes decidir qué usuarios reciben cada mensaje, segmentando conversaciones privadas o grupales fácilmente.
En la vista de chats:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sokect en Flask</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"
integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA=="
crossorigin="anonymous"></script>
</head>
<body>
<textarea id="message"></textarea>
<button onclick="sendMsj()">Enviar</button>
<button onclick="join()">Unir</button>
<button onclick="leave()">Abandonar</button>
<script>
var socket = io()
function join(){
socket.emit('join', { room:"room{{current_user.id}}"})
}
function leave(){
socket.emit('leave', { room:"room{{current_user.id}}"})
}
function sendMsj() {
message = document.querySelector("#message")
if (message.value.trim() == "")
return alert("No hay mensaje que enviar")
socket.emit('chat', { message: message.value.trim(), room:"room{{current_user.id}}"})
message.value = ""
}
socket.on('connect', function () {
console.log("Conectados!")
})
socket.on('disconnect', function () {
console.log("Desconectados!")
})
socket.on('chat', function (message) {
console.log("chat "+message)
})
socket.on('leave', function (message) {
console.log("leave "+message)
})
socket.on('join', function (message) {
console.log("join "+message)
})
</script>
<h1>Hola Mundo</h1>
</body>
</html>⚙️ Buenas prácticas y despliegue en producción
Eventlet y Gunicorn
Para producción, usa Eventlet o Gunicorn con workers asincrónicos:
$ pip install eventlet
$ socketio.run(app, host='0.0.0.0', port=5000, debug=False)Seguridad y manejo de sesiones
- Usa SECRET_KEY segura.
- Integra control de roles con decoradores personalizados.
- Aísla salas y evita emisiones globales innecesarias.
Escalabilidad y monitoreo
Flask-SocketIO puede escalar mediante Redis como backend de mensajes y balanceadores Nginx.
Esto es esencial si planeas manejar decenas de usuarios simultáneos.
Conclusión
Flask-SocketIO convierte una aplicación Flask estándar en un sistema interactivo y vivo.
No necesitas infraestructuras complejas: basta un servidor Python y unas pocas líneas para tener comunicación en tiempo real.
En mi experiencia, es una de las formas más simples y potentes de llevar un proyecto Flask a otro nivel.
Si te interesa profundizar, te recomiendo practicar con rooms, autenticación y despliegue con Eventlet: tres pilares que hacen la diferencia entre un demo y una app profesional.
❓ Preguntas frecuentes (FAQs)
- ¿Flask-SocketIO reemplaza a WebSocket?
- No. Flask-SocketIO implementa WebSocket, pero añade una capa de compatibilidad y control de eventos mucho más sencilla.
- ¿Puedo usar Flask-SocketIO con React o Vue?
- Sí. Solo necesitas el cliente de Socket.IO correspondiente (socket.io-client) en tu app frontend.
- ¿Qué hacer si los eventos no se emiten?
- Verifica que uses el mismo nombre de evento en cliente y servidor, y que tu aplicación corra con socketio.run() y no con app.run().
Acepto recibir anuncios de interes sobre este Blog.
Veremos com emplear las rooms en Flask SocketIO que nos permiten crear grupos de conexiones full duplex para los usuarios.