El protocolo WebSocket y sus casos de uso.


prefacio

El protocolo WebSocket es un protocolo de red full-duplex para comunicación en tiempo real. Se ejecuta sobre la capa de transporte, normalmente a través de una conexión TCP. En comparación con el protocolo HTTP tradicional, el protocolo WebSocket se puede implementar en una sola conexión 双向通信, 数据的实时交互por lo que funciona particularmente bien en aplicaciones con alto rendimiento en tiempo real.

1. Primera comprensión del protocolo WebSocket

1.1 ¿Qué es el protocolo WebSocket?

El protocolo WebSocket es un protocolo que permite la comunicación entre un servidor y un cliente 全双工、实时通信的协议. Supera 请求-响应el patrón del protocolo HTTP y realiza la transmisión de datos en tiempo real estableciendo una conexión persistente entre el cliente y el servidor. Las conexiones HTTP tradicionales deben establecerse y cerrarse para cada solicitud, mientras que las conexiones WebSocket siempre se pueden mantener abiertas, evitando la sobrecarga del establecimiento y cierre frecuente de conexiones .

Las características del protocolo WebSocket incluyen:

  • Comunicación full-duplex: el servidor y el cliente pueden enviar y recibir datos simultáneamente sin esperar una solicitud o respuesta del otro.
  • Conexión persistente: la conexión WebSocket permanece abierta, lo que evita el establecimiento y cierre frecuentes de conexiones y reduce los retrasos en la comunicación.
  • Baja latencia: dado que la conexión siempre está abierta, los datos se pueden transmitir en tiempo real para cumplir con los requisitos en tiempo real.
  • Menos sobrecarga de datos: en comparación con HTTP, una conexión WebSocket solo requiere una solicitud HTTP durante la fase de protocolo de enlace, lo que reduce la sobrecarga de la transmisión de datos.

1.2 La relación entre WebSocket y HTTP

Existe una estrecha relación entre el protocolo WebSocket y el protocolo HTTP, WebSocket 连接的建立需要通过 HTTP 握手来协商y su proceso básico es el siguiente:

  • UpgradeEn la fase de protocolo de enlace, el cliente primero envía una solicitud HTTP y establece un campo en el encabezado de la solicitud , lo que indica que desea actualizar a una conexión WebSocket.
  • Después de la confirmación, el servidor devuelve una respuesta HTTP, es decir, el protocolo cambia al protocolo WebSocket, lo que significa que la actualización se realizó correctamente.
  • Desde entonces, la conexión se ha actualizado del protocolo HTTP al protocolo WebSocket, logrando una comunicación de datos full-duplex en tiempo real.

La siguiente figura muestra el proceso básico para establecer una conexión WebSocket:

1.3 Proceso de protocolo de enlace de WebSocket

El protocolo de enlace de WebSocket significa que cuando se establece una conexión WebSocket, el cliente y el servidor interactúan a través del protocolo HTTP para negociar una conexión de actualización al protocolo WebSocket. El proceso de protocolo de enlace de WebSocket permite al servidor y al cliente confirmar que admiten el protocolo WebSocket y actualizar la conexión.

Los siguientes son los pasos básicos del protocolo de enlace WebSocket:

  1. El cliente envía una solicitud de protocolo de enlace: el cliente inicia el protocolo de enlace WebSocket enviando una solicitud HTTP. Esta solicitud debe contener algunos campos de encabezado específicos y Sec-WebSocket-Keycampos para verificación de seguridad.

Encabezados de solicitud de ejemplo:

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
  1. El servidor responde al protocolo de enlace: después de recibir la solicitud de protocolo de enlace, el servidor verifica Sec-WebSocket-Keyel campo y genera una clave de respuesta. Si se pasa la verificación, el servidor devolverá una respuesta HTTP, indicando una actualización del protocolo WebSocket.

Encabezados de respuesta de ejemplo:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
  1. Actualización de la conexión: una vez que el cliente recibe la respuesta del servidor, el protocolo de enlace es exitoso. En este punto, la conexión se actualizará del protocolo HTTP al protocolo WebSocket y el cliente y el servidor podrán iniciar una comunicación bidireccional en tiempo real en la misma conexión.

Cabe señalar que el cálculo del campo Sec-WebSocket-Keyy Sec-WebSocket-Acceptse basa en un mecanismo de verificación de seguridad. Sec-WebSocket-KeyEs una cadena generada aleatoriamente por el cliente. El servidor utilizará esta cadena para realizar ciertos cálculos y luego generará Sec-WebSocket-Acceptcampos para garantizar la legitimidad de la solicitud de protocolo de enlace.

La finalización exitosa del proceso de protocolo de enlace de WebSocket significa que se ha establecido una conexión WebSocket entre el cliente y el servidor, y ambas partes pueden realizar transmisión de datos en tiempo real en esta conexión. El protocolo de enlace es el punto de partida de la comunicación WebSocket y el intercambio de datos posterior seguirá el formato de marco de datos de WebSocket.

1.4 ¿Qué problema resuelve WebSocket?

El protocolo WebSocket resuelve los problemas del protocolo HTTP tradicional en términos de rendimiento en tiempo real, retraso y sobrecarga de datos. Al mantener conexiones persistentes y comunicación full-duplex, el protocolo WebSocket permite la transmisión de datos en tiempo real, adecuado para aplicaciones que requieren notificaciones oportunas y actualizaciones de datos, tales como:

  • Aplicación de chat instantáneo, los usuarios pueden recibir nuevos mensajes en tiempo real.
  • En los juegos en tiempo real, los jugadores pueden ver las acciones de otros jugadores al mismo tiempo.
  • Monitoreo del mercado de valores, los inversores pueden mantenerse al tanto de los cambios en el precio de las acciones.

En resumen, el protocolo WebSocket compensa las deficiencias del protocolo HTTP en la comunicación en tiempo real y proporciona una solución eficiente y de baja latencia para aplicaciones en tiempo real. En el siguiente contenido, profundizaremos en el formato de datos del protocolo WebSocket y su aplicación en el proyecto Spring Boot.

2. Formato de marco de datos WebSocket

2.1 Diagrama de formato de marco de datos de WebSocket

2.2 Descripción detallada de cada campo

El formato de trama de datos del protocolo WebSocket es la unidad básica utilizada para transmitir datos a través de una conexión WebSocket. Cada marco de datos contiene información de control y carga útil (datos de carga útil). La siguiente es una descripción detallada del formato de un marco de datos WebSocket y sus diversos campos:

  • FIN (1 bit) : indica si el mensaje es el último cuadro de datos. Si es 1, significa que es el último fotograma del mensaje; si es 0, hay fotogramas de datos posteriores.

  • RSV1, RSV2, RSV3 (1 bit cada uno) : bits reservados, generalmente establecidos en 0, para futuras expansiones.

  • Código de operación (4 bits) : especifica el tipo de marco de datos. Los tipos comunes son:

    • 0x0: indica que el marco de datos es un marco continuo.
    • 0x1: indica que el marco de datos es un marco de texto.
    • 0x2: indica que el marco de datos es un marco binario.
    • 0x8: Indica un marco de cierre de conexión.
    • 0x9: Indica el marco de ping, utilizado para la detección de latidos.
    • 0xA: Indica una trama Pong como respuesta a un Ping.
    • Otros valores están reservados o utilizados para extensiones.
  • MÁSCARA (1 bit) : indica si los datos de carga útil están cifrados con una máscara. La trama de datos enviada por el cliente al servidor debe estar cifrada, por lo que el bit MÁSCARA es 1.

  • Longitud de la carga útil (7 bits, 7+16 bits o 7+64 bits) : indica la longitud de los datos de la carga útil.

    • Si el valor está entre 0 y 125, indica la longitud real de los datos de carga útil.
    • Si el valor es 126, significa que los 16 bits siguientes son enteros sin signo, que se utilizan para indicar la longitud de los datos de carga útil.
    • Si el valor es 127, significa que los 64 bits siguientes son enteros sin signo, que se utilizan para indicar la longitud de los datos de carga útil.
  • Longitud de carga útil extendida (16 o 64 bits) : aparece solo cuando la longitud de la carga útil es 126 o 127 y se utiliza para indicar la longitud real de los datos de la carga útil.

  • Clave de enmascaramiento (32 bits) : aparece solo cuando el bit MÁSCARA es 1 y se utiliza para decodificar datos de carga útil. La clave de enmascaramiento es un número aleatorio de 32 bits.

  • Datos de carga útil : datos de carga útil. Si el bit MÁSCARA es 1, los datos de carga útil deben enmascararse y descifrarse, y se utiliza la clave de enmascaramiento para decodificar.

El formato del marco de datos de WebSocket permite que se transmitan diferentes tipos de datos en la misma conexión y la seguridad de los datos se puede proteger mediante una máscara. Se utilizan diferentes tipos de códigos de operación para identificar el propósito de los datos, como datos de texto, datos binarios, cierre de conexión, detección de latidos, etc.

3. Introducción de WebSocket en el proyecto SpringBoot

3.1 Crear un proyecto Spring Boot e introducir dependencias de WebSocket

Introducir las dependencias de WebSocket es muy simple, simplemente verifique WebSocket al crear un proyecto SpringBoot:

3.2 Heredar la clase TextWebSocketHandler

Para usar las funciones relacionadas de WebSocket, necesitamos heredar TextWebSocketHandlerla clase para implementar nuestra propia MyWebSocketHandlerclase. Creé un websocketpaquete y creé una clase en él MyWebSocketHandler:

Entonces necesitas anular el método interno. Aquí recreé cuatro métodos:

Los significados de estos cuatro métodos son:

  1. afterConnectionEstablishedMétodo: se llama automáticamente después de que la conexión WebSocket se establece correctamente.

  2. handleTextMessageMétodo: se llama automáticamente cuando WebSocket recibe un mensaje de texto. A menudo se utiliza para reenviar mensajes recibidos.

  3. handleTransportErrorMétodo: Se llama automáticamente cuando ocurre una excepción en la conexión.

  4. afterConnectionClosedMétodo: se llama automáticamente después de que la conexión se cierra normalmente.

Al implementar estos métodos, puede controlar el comportamiento de la conexión WebSocket, incluido el establecimiento de la conexión, el procesamiento de mensajes, el manejo de excepciones y el cierre de la conexión. Esto nos permite implementar varias lógicas de comunicación WebSocket en la aplicación.

Código de ejemplo de WebSocket:

Aquí, sólo se realizan operaciones de impresión simples sobre el establecimiento de la conexión, mensajes recibidos, desconexión de la conexión, excepciones, etc.

@Service
public class MyWebSocketHandler extends TextWebSocketHandler {
    
    
    /**
     * 这个方法会在 WebSocket 连接成功后,被自动调用
     *
     * @param session WebSocket 连接中对应的会话
     * @throws Exception 异常信息
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    
    
        System.out.println("TestWebSocketComponent 连接成功!");
    }

    /**
     * 这个方法会在 WebSocket 收到消息的时候,被自动调用
     *
     * @param session WebSocketSession
     * @param message 收到消息的值
     * @throws Exception 异常信息
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    
    
        System.out.println("TestWebSocketComponent 收到消息!" + message.toString());
        // session 是一个会话,其中记录了通信双方是谁(session 中就持有了 WebSocket 的通信连接)
        session.sendMessage(message);
    }

    /**
     * 这个方法会在连接出现异常的时候,被自动调用
     *
     * @param session   WebSocketSession
     * @param exception 异常信息
     * @throws Exception 异常信息
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
    
    
        System.out.println("TestWebSocketComponent 连接异常了!");
    }

    /**
     * 这个方法会在连接正常关闭后,被自动调用
     *
     * @param session WebSocketSession
     * @param status  关闭的状态
     * @throws Exception 异常信息
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    
    
        System.out.println("TestWebSocketComponent 连接关闭!");
    }
}

3.3 Configurar la ruta de recursos

Para que MyWebSocketHandler se pueda llamar al que acabamos de crear después de establecer la conexión WebSocket, es necesario configurarlo, es decir, registrar la relación de mapeo entre esta clase y la ruta del recurso.

  1. Primero cree un configpaquete y luego cree una clase dentro de él WebSocketConfig.
  2. Esta clase necesita implementar WebSocketConfigurerla interfaz y anular registerWebSocketHandlersel método.

Tenga en cuenta que debe agregarse @Configurationpara indicar que es una clase de configuración y almacenarse en Spring; además, @EnableWebSocketdeben agregarse anotaciones para indicar que la compatibilidad con WebSocket está habilitada para que la aplicación pueda manejar conexiones WebSocket.

@Configuration
@EnableWebSocket 
public class WebSocketConfig implements WebSocketConfigurer {
    
    
    /**
     * 通过这个方法,把刚才创建好的 Handler 类注册到具体的路径中
     *
     * @param registry WebSocketHandlerRegistry
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    
    
    }
}
  1. Finalmente, asocie lo anterior MyWebSocketHandlercon una ruta de solicitud específica.
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    
    
    @Autowired
    private MyWebSocketHandler myWebSocketHandler;

    /**
     * 通过这个方法,把刚才创建好的 Handler 类注册到具体的路径中
     *
     * @param registry WebSocketHandlerRegistry
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    
    
        // 当浏览器通过 WebSocket 请求的路径是 '/test' 的时候,就会调用到 MyWebSocketHandler 这个类中的方法
        registry.addHandler(myWebSocketHandler, "/test");
    }
}

Cuando se establece una conexión WebSocket y la ruta solicitada es , /testse llamará MyWebSocketHandleral método de esta clase . A través de esta configuración, la lógica de procesamiento de WebSocket se conecta con la ruta, de modo que la conexión WebSocket se pueda procesar y responder correctamente en la aplicación.

3.4 Código de interfaz

Escriba una página de inicio simple para probar conexiones WebSocket:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>测试 WebSocket 的使用</title>
</head>
<body>
    <input type="text" id="message">
    <button id="send-button">发送</button>

    <script>
        // 创建一个 WebSocket 实例,连接到服务器的 /test 路径
        let websocket = new WebSocket("ws://localhost:8081/test");

        // WebSocket 连接建立成功的回调函数
        websocket.onopen = function () {
      
      
            console.log("WebSocket 连接成功!");
        }

        // WebSocket 收到消息的回调函数
        websocket.onmessage = function (message) {
      
      
            console.log("WebSocket 收到消息:" + message.data);
        }

        // WebSocket 连接断开的回调函数
        websocket.onclose = function () {
      
      
            console.log("WebSocket 连接断开!");
        }

        // WebSocket 连接异常的回调函数
        websocket.onerror = function () {
      
      
            console.log("WebSocket 连接异常!");
        }

        // 获取页面元素
        let messageInput = document.querySelector("#message");
        let sendButton = document.querySelector('#send-button');

        // 发送按钮的点击事件
        sendButton.onclick = function(){
      
      
            console.log("WebSocket 发送消息:" + messageInput.value);
            websocket.send(messageInput.value); // 向服务器发送消息
        }
    </script>
</body>
</html>

Este código crea una página HTML simple con un cuadro de entrada, un botón de enviar y algo de código JavaScript para la conexión WebSocket. Específicamente:

  • Cuando se carga la página, el código JavaScript crea una instancia de WebSocket, conectada a ws://localhost:8081/testla ruta. Este WebSocketConfigcorresponde a la ruta previamente registrada en .
  • Varias funciones de devolución de llamada de WebSocket están configuradas para ocuparse del establecimiento de la conexión, la recepción de mensajes, la desconexión de la conexión y la excepción de la conexión, respectivamente.
  • Cuando el usuario ingresa texto en el cuadro de entrada y hace clic en el botón enviar, el código JavaScript se utilizará para websocket.send(messageInput.value)enviar el mensaje ingresado por el usuario al servidor.

Esta página de inicio se utiliza para comunicarse con el procesador WebSocket creado previamente. Puede abrir esta página en un navegador y luego observar el estado de la conexión WebSocket y la transmisión de mensajes en la consola.

3.5 Ejecutando la demostración

http://localhost:8081/test.htmlInicie el proyecto SpringBoot y acceda a él en el navegador :

en este punto, puede encontrar que la conexión WebSocket se ha establecido correctamente y puede observar la solicitud y la respuesta a través de la captura de paquetes.

La siguiente es la solicitud y respuesta específicas obtenidas mediante la captura de Fiddle al establecer una conexión WebSocket:

Solicitud:

Respuesta:

Ingrese "hola mundo" en la página y luego envíe:


En este punto, puede ver que el mensaje se envió correctamente a través de WebSocket en la página de inicio.

Salida del backend:

se descubre que el backend recibió con éxito el mensaje que se acaba de enviar en este momento. Luego, el mensaje recibido se puede reenviar para realizar una comunicación en tiempo real.

Supongo que te gusta

Origin blog.csdn.net/qq_61635026/article/details/132608961
Recomendado
Clasificación