Error de lectura de TCP incremental

Mucha gente siempre piensa que aprender el protocolo TCP/IP es inútil. Piensan que el desarrollo diario de la programación solo requiere saber cómo utilizar la interfaz de socket. Si ha localizado el problema en línea, sabrá que ese no es el caso. Si se usa en una LAN y todo es normal, ese puede ser el caso. Sin embargo, si el conmutador intermedio es inestable, el servidor físico está caído u otras situaciones anormales, los problemas causados ​​en este momento no se pueden solucionar si usted. Solo permanezca en el nivel de comprensión de la interfaz del socket. Por lo tanto, una comprensión profunda del protocolo TCP/IP nos resulta muy útil para analizar problemas anormales.

La siguiente figura es una arquitectura común en la comunicación de red, a saber, la arquitectura CS. El programa consta de dos partes, cliente y servidor. Por supuesto, el entorno real es mucho más complejo. Puede haber muchos tipos y números diferentes de dispositivos entre clientes y servidores, lo que aumenta la complejidad de las comunicaciones de red. Naturalmente, también aumentará la complejidad de la tolerancia a fallos en el desarrollo de programas.

Figura 1 Infraestructura

Proceso básico de TCP

Antes de analizar situaciones anormales, primero recordemos la lógica básica del protocolo TCP. Antes de que el cliente y el servidor puedan enviar y recibir datos, primero deben establecer una conexión. En la capa de protocolo, las conexiones también se establecen enviando y recibiendo paquetes, pero en la capa de usuario, el cliente llama a una función de conexión. El proceso de conexión se conoce comúnmente como "apretón de manos de tres vías" y el proceso específico se muestra en la Figura 2.

Figura 2 Proceso de protocolo de enlace de tres vías TCP

La desconexión de la conexión TCP también es más complicada y debe pasar por el proceso llamado "cuatro ondas". La razón es que TCP es una comunicación dúplex y necesita desconectar el cliente y el servidor respectivamente.

Figura 3 Las cuatro ondas de TCP

Otro contenido importante es la transición de estado del protocolo TCP. Sólo comprendiendo estos contenidos podremos comprender claramente el contenido de los paquetes de datos en diversas condiciones anormales.

Figura 4 Diagrama de transición de estado de TCP

Este artículo revisa brevemente el proceso básico de TCP. Para obtener más información, consulte el artículo anterior "De TCP a Socket, comprenda a fondo de qué se trata la programación de redes".

Análisis de situaciones anormales

Después de comprender el proceso básico de TCP, echemos un vistazo a varias situaciones anormales. Estas anomalías son la clave para nuestra posterior resolución de problemas. Comprenda estas situaciones y principios anormales y luego resuelva los problemas con facilidad.

1. Intentando establecer una conexión con un puerto inexistente (el host es normal).

El puerto inexistente aquí significa que no hay ningún programa escuchando este puerto en el lado del servidor. Nuestro cliente llama a connect para intentar establecer conexión con él. ¿Qué pasará en este momento?

En este caso, normalmente recibimos la siguiente excepción en el cliente:

[errno111] Conexión rechazada

El significado específico se puede encontrar en Linux Compruébalo en el manual correspondiente o búsquelo con un buscador. Imagine que no hay ningún programa escuchando esta interfaz en el servidor, por lo que es imposible completar el proceso de establecimiento de conexión en el servidor. En referencia al proceso de "apretón de manos de tres vías", podemos saber que cuando el paquete SYNC del cliente llega al servidor, el protocolo TCP enviará un mensaje de error al cliente para informarle que se ha producido un error. Y el mensaje de error es un mensaje que contiene RST. Estas anomalías también son fáciles de simular. Sólo necesitamos escribir un pequeño programa para conectarnos a un puerto del servidor que no está escuchando. A continuación se muestra el paquete capturado por Wirehark; puede ver el mensaje RST en rojo.

Captura de pantalla del paquete de datos de la Figura 5

Para comprender mejor, a nivel del sistema operativo, el servidor TCP en realidad lee los datos del registro de la tarjeta de red y luego los analiza. Para TCP, es natural analizar la información clave del puerto de destino y luego verificar si existe dicho socket en función de esta información. ¿Qué es este enchufe? Es un identificador de archivo a nivel de usuario, pero en realidad es una estructura de datos en el kernel que registra mucha información. Esta estructura de datos se almacena en una tabla hash y se puede buscar mediante la función _ _ inet _ lookup _ skb (net/inet _ hashtables. h). En el ejemplo anterior, el socket no se puede encontrar de forma natural, por lo que el servidor TCP manejará el error enviando un RST al cliente (a través de la función tcp_v4_send_reset).

2. Se intentó establecer una conexión con el puerto, pero el host estaba inactivo (el host estaba inactivo).

Esta también es una situación común cuando un servidor no funciona y el cliente no se da cuenta pero aún así intenta establecer una conexión con él. Este escenario también se divide en dos situaciones: una simplemente se cierra y la otra se cierra a largo plazo. ¿Por qué distinguir estas dos situaciones?

Esto está relacionado principalmente con el protocolo raíz ARP. ARP fallará en el caché local, por lo que el cliente TCP no podrá enviar paquetes al servidor de destino.

(192.168.1.100) se encuentra en 08:00:27:1a:7a:0a [ether] de eth0.

Después de comprender la situación anterior, analicemos la situación que acaba de cerrar. En este punto, el cliente puede enviar paquetes al servidor. Sin embargo, debido a que el servidor está inactivo, no se envía ninguna respuesta al cliente.

Captura de pantalla de la Figura 6 del paquete de datos

Debido a que el cliente no sabe que el servidor está inactivo, enviará paquetes SYNC repetidamente. Como se muestra en la Figura 6, puede ver que el cliente envía un paquete de sincronización al servidor cada pocos segundos. El tiempo específico está relacionado con el protocolo TCP y la implementación de diferentes sistemas operativos puede ser ligeramente diferente.

3. La aplicación del servidor se bloquea (o muere) mientras se establece una conexión.

También existe una situación en la que la aplicación del servidor se encuentra en un estado zombie durante el proceso de establecer una conexión entre los clientes. Esta situación ocurre a menudo en la práctica (asumimos que solo la aplicación es un zombie y el. El kernel no es zombies). ¿Qué pasará en este momento? ¿Se puede realizar TCP tres veces? ¿El cliente puede enviar y recibir datos?

A nivel de usuario, sabemos que el servidor devuelve un nuevo socket a través de la interfaz de aceptación y luego puede intercambiar datos con el cliente. Es decir, a nivel de usuario, el resultado devuelto por aceptar indica que el protocolo de enlace de tres vías se ha completado; de lo contrario, se bloqueará la aceptación. En nuestra situación hipotética, en realidad significa que la solicitud no puede ser aceptada.

Para comprender completamente el problema hipotético anterior, es necesario comprender dos puntos: uno es qué hace específicamente la función de aceptación y el otro es la naturaleza del protocolo de enlace de tres vías de TCP.

Intentemos entender el primer punto. Accept ingresará al kernel a través de una interrupción suave y, finalmente, llamará a la función inet_csk_accept del protocolo tcp. Esta función descubrirá en la cola si hay un socket en el estado establecido. Si es así, devuelva el socket; de lo contrario, bloquee el proceso actual. En otras palabras, este es solo un proceso de consulta y no implica ninguna lógica de protocolo de enlace de tres partes.

¿Cuál es la esencia del apretón de manos de tres vías? De hecho, es un proceso de comunicación continuo entre el cliente y el servidor. Este proceso de comunicación se completa a través de tres paquetes de datos. El envío y procesamiento de este paquete se realiza en realidad en el kernel. Para el servidor TCP, cuando recibe el paquete SYNC, creará una estructura de datos de socket y responderá ACK al cliente. Cuando recibe nuevamente el ACK del cliente, cambia el estado de la estructura de datos del socket a ESTABLECIDO y lo envía a la cola lista. Todo este proceso no tiene nada que ver con la solicitud.

Cuando el socket anterior se agrega a la cola lista, la función de aceptación se activa y luego puede obtener y devolver un nuevo socket. Pero miremos atrás. Antes de aceptar la devolución, el protocolo de enlace de tres vías se ha completado, es decir, se ha establecido la conexión.

La otra es si el cliente puede enviar datos si acepta y no regresa. La respuesta es sí. Porque los datos se envían y reciben en modo kernel. Después de que el cliente envía datos, la tarjeta de red del servidor los recibirá primero, luego notificará a la capa IP a través de una interrupción y luego los cargará a la capa TCP. La capa TCP almacena datos en buffers relevantes según el puerto y la dirección de destino. Si la aplicación tiene una operación de lectura (como lectura o recepción) en este momento, los datos se copiarán del búfer en modo kernel al caché en modo usuario. De lo contrario, los datos siempre estarán en el búfer del estado del kernel. En términos generales, si el cliente TCP puede enviar datos no tiene nada que ver con si el programa del servidor está funcionando.

Por supuesto, si toda la máquina se atasca, esa es otra situación. Esta situación ya es la segunda situación que analizamos antes. Porque, debido a que la máquina está completamente atascada, el servidor TCP no puede aceptar ningún mensaje y, naturalmente, no puede enviar ningún mensaje de respuesta al cliente.

Resumen

Hoy presentamos principalmente varias situaciones anormales durante el proceso de establecimiento de la conexión, y hay otra situación durante el proceso de transmisión de datos. Por ejemplo, el servidor se queda sin energía repentinamente durante el proceso de transmisión, o el programa falla, etc. Más adelante presentaremos en detalle el rendimiento de estas excepciones en la capa de protocolo.

rc="../css/tongji.js">