Introducción: por qué WebSocket y Kotlin son la pareja ideal para real-time
Las aplicaciones web modernas requieren cada vez más transferencia instantánea de datos: desde chats y juegos en línea hasta cotizaciones bursátiles y sistemas de monitoreo. El HTTP tradicional con su modelo de solicitud-respuesta es ineficiente para estas tareas: crea retrasos y tráfico redundante. Aquí es donde viene al rescate WebSocket, un protocolo que proporciona una conexión bidireccional permanente entre el cliente y el servidor.
Kotlin, con su sintaxis concisa, compatibilidad total con Java y potente soporte para coroutines, es ideal para crear aplicaciones real-time. El framework Ktor de JetBrains proporciona soporte integrado para WebSocket, permitiendo escribir código eficiente y seguro en literalmente unas pocas líneas.
En este artículo, analizaremos cómo crear una aplicación real-time completa en Kotlin usando WebSocket. Aprenderás:
- Cómo configurar un servidor WebSocket en Ktor
- Cómo conectarte a él desde un navegador o una aplicación móvil
- Cómo organizar el intercambio de mensajes en tiempo real
- Qué patrones y enfoques usar para escalar
1. Fundamentos de WebSocket y sus ventajas en Kotlin
¿Qué es WebSocket?
WebSocket es un protocolo que funciona sobre TCP. Después de establecer la conexión mediante un handshake HTTP (upgrade), el cliente y el servidor pueden intercambiar datos en ambas direcciones sin solicitudes repetidas. Esto reduce drásticamente la latencia y disminuye la carga en la red.
¿Por qué Kotlin?
- Coroutines — permiten manejar miles de conexiones WebSocket simultáneas sin bloquear hilos.
- Ktor — un framework asíncrono ligero con soporte nativo para WebSocket.
- Type safety — errores en tiempo de compilación, no en tiempo de ejecución.
- Multiplataforma — el mismo código puede funcionar en JVM, JS y Native.
2. Creación de un servidor WebSocket en Ktor
Paso 1: Configuración del proyecto
Agrega las dependencias en build.gradle.kts:
dependencies { implementation("io.ktor:ktor-server-core:2.3.0") implementation("io.ktor:ktor-server-netty:2.3.0") implementation("io.ktor:ktor-server-websockets:2.3.0") implementation("ch.qos.logback:logback-classic:1.4.11")}Paso 2: Servidor básico con WebSocket
import io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.websocket.*import io.ktor.websocket.*import kotlinx.coroutines.delay
fun main() { embeddedServer(Netty, port = 8080) { install(WebSockets) webSocket("/chat") { send(Frame.Text("¡Bienvenido al chat!")) for (frame in incoming) { if (frame is Frame.Text) { val text = frame.readText() println("Recibido: $text") send(Frame.Text("Eco: $text")) } } } }.start(wait = true)}Este código crea un servidor echo simple. Al conectarse, el cliente recibe un saludo, y cada mensaje suyo se devuelve con el prefijo "Eco:".
Paso 3: Manejo de múltiples clientes y difusión
Para un chat real-time, es necesario almacenar una lista de sesiones activas:
import io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.websocket.*import io.ktor.websocket.*import kotlinx.coroutines.channels.ConcurrentHashMap
val clients = ConcurrentHashMap<String, WebSocketSession>()
fun main() { embeddedServer(Netty, port = 8080) { install(WebSockets) webSocket("/chat") { val userName = "User_${System.currentTimeMillis()}" clients[userName] = this try {