Long Polling vs WebSocket en Kotlin: qué elegir para tiempo real

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Long Polling vs WebSocket en Kotlin: qué elegir para tiempo real

\n\n

Imagina: estás escribiendo un chat en Kotlin, un terminal bursátil o un sistema de monitoreo de servidores. El cliente necesita ver los cambios al instante. La solicitud HTTP tradicional de «ir y responder» no sirve aquí: los datos deben llegar solos, sin constantes «toques» del usuario.

\n\n

En el mundo de Kotlin hay dos enfoques populares: Long Polling y WebSocket. Ambos permiten organizar la interacción en tiempo real, pero lo hacen de formas fundamentalmente diferentes. ¿Cuál elegir? Analicémoslo con ejemplos prácticos, sin rodeos ni lecciones académicas.

\n\n

¿Qué es Long Polling (y por qué no ha muerto)?

\n\n

Long Polling es una técnica en la que el cliente envía una solicitud HTTP y el servidor no responde de inmediato, sino que «se queda abierto» hasta que aparecen nuevos datos. Tan pronto como los datos aparecen, el servidor envía la respuesta, el cliente la procesa e inmediatamente abre una nueva solicitud. El ciclo se repite.

\n\n

Parece HTTP normal, pero con un tiempo de espera largo. Sin protocolos adicionales, sin handshakes: todo funciona sobre HTTP/1.1 o HTTP/2 estándar.

\n\n

Ejemplo de Long Polling en Kotlin (Ktor Server + OkHttp Client)

\n\n

Parte del servidor en Ktor (el servidor esperará hasta que aparezca un mensaje):

\n\n
import io.ktor.server.engine.*\nimport io.ktor.server.netty.*\nimport io.ktor.server.routing.*\nimport io.ktor.server.response.*\nimport io.ktor.http.*\nimport kotlinx.coroutines.*\n\nfun main() {\n    embeddedServer(Netty, port = 8080) {\n        routing {\n            get("/long-poll") {\n                // Simulación de espera de un nuevo mensaje\n                val message = withContext(Dispatchers.Default) {\n                    delay(5000) // esperamos 5 segundos (o un nuevo evento)\n                    "Nuevo mensaje: ${System.currentTimeMillis()}"\n                }\n                call.respondText(message, ContentType.Text.Plain)\n            }\n        }\n    }.start(wait = true)\n}\n
\n\n

Cliente con OkHttp:

\n\n
import okhttp3.*\n\nval client = OkHttpClient.Builder()\n    .readTimeout(30, TimeUnit.SECONDS) // ¡punto importante!\n    .build()\n\nfun startLongPolling() {\n    val request = Request.Builder()\n        .url("http://localhost:8080/long-poll")\n        .build()\n\n    client.newCall(request).enqueue(object : Callback {\n        override fun onFailure(call: Call, e: IOException) {\n            e.printStackTrace()\n            // Obligatorio reiniciar el polling en caso de error\n            startLongPolling()\n        }\n\n        override fun onResponse(call: Call, response: Response) {\n            response.use {\n                if (response.isSuccessful) {\n                    println("Recibido: ${response.body?.string()}")\n                    // Iniciamos inmediatamente la siguiente solicitud\n                    startLongPolling()\n                }\n            }\n        }\n    })\n}\n
\n\n

Ventajas de Long Polling:

\n
    \n
  • Funciona en todas partes, incluso detrás de proxies corporativos y en navegadores antiguos
  • \n
  • Depuración simple: ves solicitudes HTTP normales en los registros
  • \n
  • Fácil de integrar en la infraestructura existente (balanceadores, cachés, CDN)
  • \n
\n\n

Desventajas:

\n
    \n <>Alta latencia: entre el envío de la solicitud y la recepción de la respuesta puede pasar hasta un RTT (Round Trip Time)\n
  • El servidor mantiene muchas conexiones abiertas (cada solicitud es un hilo/corutina separado)
  • \n
  • Al reconectarse, es posible la pérdida de mensajes (si no se implementa idempotencia)
  • \n
\n\n

WebSocket: dúplex completo

\n\n

WebSocket es un protocolo separado (ws://) que establece una conexión bidireccional permanente después del handshake HTTP. El servidor y el cliente pueden enviar mensajes en cualquier momento, sin la sobrecarga de los encabezados.

\n\n

Ejemplo de WebSocket en Kotlin (Ktor Server + Ktor Client)<

Blogs

Book Recommendations