WebSockets en Java: desde chats hasta gráficos bursátiles en 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

WebSockets en Java: cuando HTTP ya no es suficiente

\n\n

Imagínese una bolsa de valores en línea. Usted mira el gráfico del precio del bitcoin. Cada segundo los números cambian. O un juego multijugador donde usted mueve a su personaje y otros cien jugadores lo ven al instante. O simplemente un chat corporativo donde los mensajes llegan sin presionar F5.

\n\n

¿Cómo funciona esto bajo el capó? Antes, los desarrolladores se las ingeniaban: polling (el cliente pregunta al servidor cada segundo "¿hay novedades?"), long polling (el servidor mantiene la conexión hasta que haya una novedad), Server-Sent Events (flujo unidireccional). Todo esto son parches. El protocolo HTTP fue creado originalmente como solicitud-respuesta. No sabe "empujar" datos por sí mismo.

\n\n

Aquí es donde entran en juego los WebSockets. Es un protocolo que establece una conexión una vez y la mantiene abierta. El servidor puede enviar datos al cliente en cualquier momento, y viceversa. Comunicación bidireccional en tiempo real, sin la sobrecarga de los encabezados HTTP.

\n\n

En este artículo analizaremos los WebSockets en Java de principio a fin. Escribiremos un chat completo, exploraremos los problemas comunes y compararemos las librerías más populares. Si usted es desarrollador Java y quiere crear aplicaciones en tiempo real con Java, está en el lugar correcto.

\n\n

¿Cómo funciona WebSocket? Breve introducción

\n\n

WebSocket no es magia, es simplemente un protocolo sobre TCP. Comienza como una solicitud HTTP normal (handshake) y luego se "actualiza" a un canal bidireccional permanente.

\n\n

Etapa 1: Handshake (Apretón de manos)

\n

El cliente envía una solicitud HTTP GET normal con el encabezado Upgrade: websocket. El servidor responde con el código 101 Switching Protocols. Eso es todo. A partir de este momento, los datos no viajan como paquetes HTTP, sino como tramas WebSocket.

\n\n

Etapa 2: Tramas de datos

\n

Los datos se transmiten en pequeños paquetes (tramas). Una trama puede ser de texto (una cadena normal) o binaria (imagen, audio). Las librerías de Java ocultan esta complejidad: usted trabaja simplemente con cadenas o bytes.

\n\n

Etapa 3: Cierre

\n

Cualquier parte puede iniciar el cierre de la conexión enviando una trama especial de cierre (Close).

\n\n

¿Suena simple? Así es. Pero el diablo está en los detalles: tiempos de espera, reconexiones, escalabilidad. Pero de eso hablaremos más adelante.

\n\n

Librerías para WebSockets en Java

\n\n

En el ecosistema Java existen tres enfoques principales:

\n\n
    \n
  • Jakarta WebSocket (JSR 356) — el estándar de Java EE / Jakarta EE. Funciona en cualquier servidor compatible (Tomcat, Jetty, GlassFish). Muchas anotaciones, poco código.
  • \n
  • Spring WebSocket — una capa sobre el estándar en el ecosistema Spring. Proporciona integración con Security, STOMP (protocolo sobre WebSocket para suscripciones a tópicos) y plantillas convenientes.
  • \n
  • Netty / Vert.x / Undertow — frameworks asíncronos de bajo nivel. Máximo rendimiento, pero más código.
  • \n
\n\n

Para el 90% de las tareas, Jakarta o Spring son suficientes. Revisaremos ambas opciones con ejemplos reales.

\n\n

Ejemplo 1: Chat simple con Jakarta WebSocket (sin Spring)

\n\n

Supongamos que tenemos un viejo y querido Tomcat 10+ (Jakarta EE). Necesitamos un endpoint del servidor y un cliente (HTML+JS).

\n\n

Servidor: clase endpoint

\n
import jakarta.websocket.*;\nimport jakarta.websocket.server.ServerEndpoint;\nimport java.io.IOException;\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArraySet;\n\n@ServerEndpoint("/chat")\npublic class ChatEndpoint {\n\n    // Almacenamos todas las sesiones activas (conjunto thread-safe)\n    private static final Set<Session> sessions = new CopyOnWriteArraySet<>();\n\n    @OnOpen\n    public void onOpen(Session session) {\n        sessions.add(session);\n        broadcast("Usuario conectado. Total en el chat: " + sessions.size());\n    }\n\n    @OnMessage\n    public void onMessage(String message, Session session) {\n        // Se puede añadir lógica: enviar solo a                

Blogs

Book Recommendations