Introducción a WebSocket en Kotlin: de la teoría a la práctica en tiempo real
Las aplicaciones web modernas requieren cada vez más un intercambio instantáneo de datos entre el cliente y el servidor. El protocolo HTTP tradicional, que funciona bajo el principio de "solicitud-respuesta", no es adecuado para tareas donde la información debe llegar en tiempo real: chats en línea, cotizaciones bursátiles, juegos multijugador o notificaciones push. Aquí es donde WebSocket viene al rescate: un protocolo que proporciona una conexión bidireccional permanente.
Kotlin, siendo un lenguaje moderno para JVM, JavaScript y Native, ofrece excelentes herramientas para trabajar con WebSocket. En este artículo, analizaremos cómo crear aplicaciones en tiempo real con Kotlin utilizando la biblioteca Ktor, un framework popular para construir servidores y clientes asíncronos. Aprenderá cómo configurar una conexión WebSocket, enviar y recibir mensajes, manejar errores y construir soluciones escalables.
1. Fundamentos de WebSocket: ¿por qué Kotlin y Ktor?
WebSocket es un protocolo que, después de establecer una conexión mediante un handshake HTTP, cambia el canal a un modo bidireccional permanente. A diferencia de HTTP, el servidor puede iniciar el envío de datos sin una solicitud del cliente. Esto es ideal para escenarios en tiempo real.
Kotlin junto con Ktor ofrece:
- Asincronía — las corutinas de Kotlin permiten manejar miles de conexiones simultáneas sin bloquear hilos.
- Multiplataforma — el mismo código puede funcionar en JVM, JavaScript y Native.
- Concisión — mínimo código boilerplate, máxima expresividad.
- Seguridad — soporte integrado para SSL/TLS, autenticación y CORS.
Pasemos a la práctica y creemos un servidor y cliente WebSocket simple en Kotlin.
2. Creación de un servidor WebSocket en Kotlin con Ktor
2.1. Configuración del proyecto
Para empezar, cree un nuevo proyecto Gradle o Maven. Agregue las dependencias de Ktor 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")}2.2. Implementación del servidor
Creemos un servidor WebSocket que acepte conexiones, lea mensajes y responda a ellos. El siguiente ejemplo utiliza la biblioteca Ktor con corutinas:
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)}Aquí:
- Instalamos el plugin
WebSockets. - Definimos el endpoint
/chat. - En la corutina procesamos los frames entrantes y enviamos una respuesta eco.
2.3. Manejo de errores y cierre de conexión
En aplicaciones reales, es importante manejar correctamente las interrupciones de la conexión. Agreguemos manejo de excepciones y cierre de sesión:
webSocket("/chat") { try { send(Frame.Text("Conexión establecida")) for (frame in incoming) { when (frame) { is Frame.Text -> { val text = frame.readText() if (text.equals("exit", ignoreCase = true)) { cl