1. Información general
En este tutorial, repasaremos los conceptos básicos de la comunicación cliente-servidor y exploraremos esto a través de dos opciones populares disponibles en la actualidad. Veremos cómo WebSocket, que es un nuevo participante, se compara con la opción más popular de HTTP RESTful.
2. Conceptos básicos de la comunicación en red
Antes de profundizar en los detalles de las diferentes opciones y sus méritos y desventajas, actualicemos rápidamente el panorama de la comunicación en red. Esto ayudará a poner las cosas en perspectiva y comprenderlo mejor.
Las comunicaciones de red se pueden entender mejor en términos del modelo de interconexión de sistemas abiertos (OSI).
El modelo OSI divide el sistema de comunicación en siete capas de abstracción:

En la parte superior de este modelo se encuentra la capa Aplicación, que es de nuestro interés en este tutorial. Sin embargo, discutiremos algunos aspectos en las cuatro capas superiores a medida que avanzamos comparando WebSocket y RESTful HTTP.
La capa de aplicación es la más cercana al usuario final y es responsable de interactuar con las aplicaciones que participan en la comunicación. Hay varios protocolos populares que se utilizan en esta capa como FTP, SMTP, SNMP, HTTP y WebSocket.
3. Descripción de WebSocket y HTTP RESTful
Si bien la comunicación puede ocurrir entre cualquier número de sistemas, estamos particularmente interesados en la comunicación cliente-servidor. Más específicamente, nos centraremos en la comunicación entre un navegador web y un servidor web. Este es el marco que usaremos para comparar WebSocket con RESTful HTTP.
Pero antes de continuar, ¿por qué no comprender rápidamente qué son?
3.1. WebSockets
Según la definición formal, WebSocket es un protocolo de comunicación que presenta comunicación bidireccional y dúplex completo a través de una conexión TCP persistente. Ahora, entenderemos cada parte de esta declaración en detalle a medida que avancemos.
WebSocket fue estandarizado como protocolo de comunicación por IETF como RFC 6455 en 2011. La mayoría de los navegadores web modernos admiten el protocolo WebSocket.
3.2. HTTP RESTful
Si bien todos conocemos HTTP debido a su presencia omnipresente en Internet, también es un protocolo de comunicación de la capa de aplicación. HTTP es un protocolo basado en solicitudes y respuestas ; de nuevo, lo entenderemos mejor más adelante en el tutorial.
REST (Representational State Transfer) es un estilo arquitectónico que impone un conjunto de restricciones a HTTP para crear servicios web.
4. Subprotocolo de WebSocket
Si bien WebSocket define un protocolo para la comunicación bidireccional entre el cliente y el servidor, no impone ninguna condición al mensaje que se intercambiará . Esto se deja abierto para que las partes en la comunicación acuerden como parte de la negociación de subprotocolo.
No es conveniente desarrollar un subprotocolo para aplicaciones no triviales. Afortunadamente, hay muchos subprotocolos populares como STOMP disponibles para su uso . STOMP son las siglas de Simple Text Oriented Messaging Protocol y funciona sobre WebSocket. Spring Boot tiene soporte de primera clase para STOMP, que usaremos en nuestro tutorial.
5. Configuración rápida en Spring Boot
No hay nada mejor que ver un ejemplo funcional. Por lo tanto, crearemos casos de uso simples tanto en WebSocket como en HTTP RESTful para explorarlos más y luego compararlos. Creemos un componente simple de servidor y cliente para ambos.
Crearemos un cliente simple usando JavaScript que enviará un nombre. Y crearemos un servidor usando Java que responderá con un saludo.
5.1. WebSocket
Para usar WebSocket en Spring Boot, necesitaremos el iniciador apropiado:
org.springframework.boot spring-boot-starter-websocket
Ahora configuraremos los puntos finales de STOMP:
@Configuration @EnableWebSocketMessageBroker public class WebSocketMessageBrokerConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws"); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.setApplicationDestinationPrefixes("/app"); config.enableSimpleBroker("/topic"); } }
Definamos rápidamente un servidor WebSocket simple que acepta un nombre y responde con un saludo:
@Controller public class WebSocketController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(Message message) throws Exception { return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"); } }
Finalmente, construyamos el cliente para comunicarse con este servidor WebSocket. Como estamos enfatizando la comunicación de navegador a servidor, creemos un cliente en JavaScript:
var stompClient = null; function connect() { stompClient = Stomp.client('ws://localhost:8080/ws'); stompClient.connect({}, function (frame) { stompClient.subscribe('/topic/greetings', function (response) { showGreeting(JSON.parse(response.body).content); }); }); } function sendName() { stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); } function showGreeting(message) { $("#greetings").append("" + message + ""); }
Esto completa nuestro ejemplo de trabajo de un servidor y cliente WebSocket. Hay una página HTML en el repositorio de código que proporciona una interfaz de usuario sencilla para interactuar.
Si bien esto solo rasca la superficie, WebSocket con Spring se puede usar para crear clientes de chat complejos y más.
5.2. HTTP RESTful
Ahora pasaremos por una configuración similar para el servicio RESTful. Nuestro sencillo servicio web aceptará una solicitud GET con un nombre y responderá con un saludo.
Usemos el iniciador web de Spring Boot en su lugar esta vez:
org.springframework.boot spring-boot-starter-web
Ahora, definiremos un punto final REST aprovechando el potente soporte de anotaciones disponible en Spring:
@RestController @RequestMapping(path = "/rest") public class RestAPIController { @GetMapping(path="/{name}", produces = "application/json") public String getGreeting(@PathVariable("name") String name) { return "{\"greeting\" : \"Hello, " + name + "!\"}"; } }
Finalmente, creemos un cliente en JavaScript:
var request = new XMLHttpRequest() function sendName() { request.open('GET', '//localhost:8080/rest/'+$("#name").val(), true) request.onload = function () { var data = JSON.parse(this.response) showGreeting(data.greeting) } request.send() } function showGreeting(message) { $("#greetings").append("" + message + ""); }
¡Eso es practicamente todo! Nuevamente, hay una página HTML en el repositorio de código para trabajar con una interfaz de usuario.
Aunque profunda en su simplicidad, definir API REST de grado de producción puede ser una tarea mucho más extensa.
6. Comparación de WebSocket y RESTful HTTP
Habiendo creado ejemplos mínimos, pero funcionales, de WebSocket y RESTful HTTP, ahora estamos listos para comprender cómo se comportan entre sí. Examinaremos esto contra varios criterios en las siguientes subsecciones.
Es importante señalar que, si bien podemos comparar directamente HTTP y WebSocket, ya que ambos son protocolos de capa de aplicación, no es natural comparar REST con WebSocket . Como vimos anteriormente, REST es un estilo arquitectónico que aprovecha HTTP para la comunicación.
Por lo tanto, nuestra comparación con WebSocket se basará principalmente en las capacidades, o la falta de ellas, en HTTP .
6.1. Esquema de URL
Una URL define la ubicación única de un recurso web y el mecanismo para recuperarlo . En una comunicación cliente-servidor, la mayoría de las veces buscamos obtener recursos estáticos o dinámicos a través de su URL asociada.
Todos estamos familiarizados con el esquema de URL HTTP:
//localhost:8080/rest
El esquema de URL de WebSocket tampoco es muy diferente:
ws://localhost:8080/ws
Al principio, la única diferencia parece ser los caracteres antes de los dos puntos, pero abstrae mucho de lo que sucede bajo el capó. Exploremos más.
6.2. Apretón de manos
Handshake se refiere a la forma automática de negociar el protocolo de comunicación entre las partes que se comunican . HTTP es un protocolo sin estado y funciona en un mecanismo de solicitud-respuesta. En cada solicitud HTTP, se establece una conexión TCP con el servidor a través del socket.
The client then waits until the server responds with the resource or an error. The next request from the client repeats everything as if the previous request never happened:

WebSocket works very differently compared to HTTP and starts with a handshake before actual communication.
Let's see what comprise a WebSocket handshake:

In case of WebSocket, the client initiates a Protocol Handshake request in HTTP and then waits until the server responds accepting an upgrade to WebSocket from HTTP.
Of course, since Protocol Handshake happens over HTTP, it follows the sequence from the previous diagram. But once the connection is established, from there on client and server switches over to WebSocket for further communication.
6.3. Connection
As we saw in the previous subsection, one stark difference between WebSocket and HTTP is that WebSocket works on a persistent TCP connection while HTTP creates a new TCP connection for every request.
Now obviously creating new TCP connection for every request is not very performant and HTTP has not been unaware of this. In fact, as part of HTTP/1.1, persistent connections were introduced to alleviate this shortcoming of HTTP.
Nevertheless, WebSocket has been designed from the ground up to work with persistent TCP connections.
6.4. Communication
The benefit of WebSocket over HTTP is a specific scenario that arises from the fact that the client can server can communicate in ways which were not possible with good old HTTP.
For instance, in HTTP, usually the client sends that request, and then the server responds with requested data. There is no generic way for the server to communicate with the client on its own. Of course, patterns and solutions have been devised to circumvent this like Server-Sent Events (SSE), but these were not completely natural.
With WebSocket, working over persistent TCP communication, it's possible for server and client both to send data independent of each other, and in fact, to many communicating parties! This is referred to as bi-directional communication.
Another interesting feature of WebSocket communication is that it's full-duplex. Now while this term may sound esoteric; it simply means that both server and client can send data simultaneously. Compare this with what happens in HTTP where the server has to wait until it receives the request in full before it can respond with data.
While the benefit of bi-directional and full-duplex communication may not be apparent immediately. we'll see some of the use-cases where they unlock some real power.
6.5. Security
Last but not least, both HTTP and WebSocket leverage the benefits of TLS for security. While HTTP offers https as part of their URL scheme to use this, WebSocket has wss as part of their URL scheme for the same effect.
So the secured version of URLs from the previous subsection should look like:
//localhost:443/rest wss://localhost:443/ws
Securing either a RESTful service or a WebSocket communication is a subject of much depth and can not be covered here. For now, let's just say that both are adequately supported in this regard.
6.6. Performance
We must understand that WebSocket is a stateful protocol where communication happens over a dedicated TCP connection. On the other hand, HTTP is inherently a stateless protocol. This has an impact on how these will perform with the load but that really depends on the use case.
Since communication over WebSocket happens over a reusable TCP connection, the overhead per message is lower compared to HTTP. Hence it can reach higher throughput per server. But there is a limit to which a single server can scale and that is where WebSocket has issues. It's not easy to horizontally scale applications with WebSockets.
This is where HTTP shines. With HTTP each new request can potentially land on any server. This implies that to increase overall throughput we can easily add more servers. This should potentially have no impact on the application running with HTTP.
Obviously an application may itself need state and session stickiness which can make it easier said than done.
7. Where Should We Use Them?
Now, we have seen enough of RESTful service over HTTP and simple communication over WebSocket to form our opinion around them. But where should we use what?
It's important to remember that while WebSocket has emerged out of shortcomings in HTTP, it's not, in fact, a replacement of HTTP. So they both have their place and their uses. Let's quickly understand how can we make a decision.
For the bulk of the scenario where occasional communication is required with the server like getting the record of an employee, it's still sensible to use REST service over HTTP/S. But for newer client-side applications like a stock-price application which requires real-time updates from the server, it's much convenient to leverage WebSocket.
Generalizing, WebSocket is more suitable for cases where a push-based and real-time communication defines the requirement more appropriately. Additionally, WebSocket works well for scenarios where a message needs to be pushed to multiple clients simultaneously. These are the cases where client and server communication over RESTful services will find it difficult if not prohibitive.
Sin embargo, el uso de servicios WebSocket y RESTful sobre HTTP debe basarse en los requisitos. Como no existen soluciones mágicas, no podemos esperar elegir una para resolver todos los problemas. Por lo tanto, debemos usar nuestra sabiduría junto con el conocimiento para diseñar un modelo de comunicación eficiente.
8. Conclusión
En este tutorial, revisamos los conceptos básicos de la comunicación de red con énfasis en los protocolos de capa de aplicación HTTP y WebSocket. Vimos algunas demostraciones rápidas de WebSocket y RESTful API sobre HTTP en Spring Boot.
Y finalmente, comparamos las características de los protocolos HTTP y WebSocket y discutimos brevemente cuándo usar cada uno.
Como siempre, el código de los ejemplos está disponible en GitHub.