Soy tráfico de red y deseo dividir cada sesión TCP en una serie de solicitudes y respuestas (los protocolos con los que estoy trabajando funcionan de esa manera, como HTTP o SSL).
Tenía una suposición simple (ignorar los paquetes fuera de servicio y reenviados): dada una porción de datos que debe enviarse, se enviará utilizando los paquetes más grandes posibles y el último paquete será más pequeño que el tamaño máximo o se seguirá por un paquete del otro lado (ignorando los paquetes vacíos ACK). Entonces, en una sesión HTTP, espero ver algo como (de nuevo, sin tener en cuenta los acks):
Paquete 1 - Solicitar "Obtener ..."
Paquete 2 - Respuesta, tamaño 1434
Paquete 3 - Respuesta, tamaño 1434
Paquete 4 - Respuesta, tamaño 1434
Paquete 5 - Respuesta, tamaño 500
Que es lo que obtengo en la mayoría de las sesiones, sin embargo, hay al menos una ocasión que vi que parecía
Paquete 1 - Solicitar "Obtener ..."
Paquete 2 - Respuesta, tamaño 1434
Paquete 3 - Respuesta, tamaño 1080
Paquete 4 - Respuesta, tamaño 1434
Paquete 5 - Respuesta, tamaño 500
Sin retransmisiones, paquetes fuera de servicio aquí o sin retrasos excepcionales en el servidor.
Quiero saber: ¿qué puede causar esto y cuándo ocurrirá? ¿Qué tan errónea es mi suposición?
ACTUALIZAR
Pongo un archivo pcap de ejemplo aquí
ACTUALIZACIÓN 2
Incluyendo un tshark
volcado con campos relevantes ...
$ tshark -r http_1082.pcap -T fields -e frame.number -e frame.len \
-e ip.src -e ip.dst -e tcp.flags.push -e http.request.method \
-e http.request.uri -e http.response.code | head -n 47
1 66 192.168.1.103 206.33.49.126 0
2 62 206.33.49.126 192.168.1.103 0
3 64 192.168.1.103 206.33.49.126 0
4 411 192.168.1.103 206.33.49.126 1 GET /money/.element/script/3.0/video/xmp/xmp_playlistapi.js
5 54 206.33.49.126 192.168.1.103 0
6 1434 206.33.49.126 192.168.1.103 0
7 1434 206.33.49.126 192.168.1.103 0
8 64 192.168.1.103 206.33.49.126 0
9 1434 206.33.49.126 192.168.1.103 0
10 1434 206.33.49.126 192.168.1.103 0
11 1434 206.33.49.126 192.168.1.103 0
12 64 192.168.1.103 206.33.49.126 0
13 1434 206.33.49.126 192.168.1.103 0
14 1434 206.33.49.126 192.168.1.103 0
15 1434 206.33.49.126 192.168.1.103 0
16 1434 206.33.49.126 192.168.1.103 0
17 64 192.168.1.103 206.33.49.126 0
18 1434 206.33.49.126 192.168.1.103 0
19 1434 206.33.49.126 192.168.1.103 0
20 1434 206.33.49.126 192.168.1.103 0
21 1434 206.33.49.126 192.168.1.103 0
22 1434 206.33.49.126 192.168.1.103 0
23 64 192.168.1.103 206.33.49.126 0
24 1434 206.33.49.126 192.168.1.103 0
25 1434 206.33.49.126 192.168.1.103 0
26 1434 206.33.49.126 192.168.1.103 0
27 1434 206.33.49.126 192.168.1.103 0
28 1434 206.33.49.126 192.168.1.103 0
29 1434 206.33.49.126 192.168.1.103 0
30 64 192.168.1.103 206.33.49.126 0
31 1434 206.33.49.126 192.168.1.103 0
32 1434 206.33.49.126 192.168.1.103 0
33 1434 206.33.49.126 192.168.1.103 0
34 1082 206.33.49.126 192.168.1.103 1 <------ Packet in question
35 1434 206.33.49.126 192.168.1.103 0
36 1434 206.33.49.126 192.168.1.103 0
37 1434 206.33.49.126 192.168.1.103 0
38 64 192.168.1.103 206.33.49.126 0
39 1434 206.33.49.126 192.168.1.103 0
40 1434 206.33.49.126 192.168.1.103 0
41 1434 206.33.49.126 192.168.1.103 0
42 1434 206.33.49.126 192.168.1.103 0
43 1434 206.33.49.126 192.168.1.103 0
44 1434 206.33.49.126 192.168.1.103 0
45 1434 206.33.49.126 192.168.1.103 0
46 626 206.33.49.126 192.168.1.103 1 200
47 64 192.168.1.103 206.33.49.126 0
Respuestas:
La capa TCP utiliza el algoritmo Nagle para almacenar el tráfico en el búfer (envía menos paquetes grandes, en lugar de más paquetes pequeños ... lo que lo hace más eficiente); hay una manera para que la aplicación diga 'enviarlo ahora'. Usted ve eso en el encabezado TCP con una bandera llamada bit PSH (push). Mientras la pila establece el bit, la inserción se realiza a petición de la aplicación.
Entonces este es un comportamiento intencionado y normal.
fuente
El tamaño del paquete depende de cómo la aplicación y / o el sistema operativo almacenan y envían datos de la red. Si la aplicación y / o el sistema operativo deciden enviar los datos después de que 1080 bytes estén en el búfer, entonces el paquete será de 1080 bytes (más encabezados). Podría haber muchas razones para que haga eso. En su caso, debería buscar en el código fuente del servidor web y / o la pila de red del sistema operativo.
fuente
El tamaño del paquete está definido por el sistema operativo (en general) y está relacionado con los buffers, la cantidad de datos proporcionados por la aplicación, etc. Muchas estrategias se pueden utilizar para lograr el máximo rendimiento y, a veces, enviar paquetes más pequeños puede ser más rápido que esperar para crear Un paquete más grande.
A veces, la cantidad de aplicaciones en ejecución puede exigir que el sistema operativo sea más rápido (envíe lo que tenga en el búfer hasta ahora) en lugar de saturar el búfer.
Tal vez, podría darnos más detalles sobre el escenario con el que estaba trabajando (por ejemplo: sistema operativo del servidor, aplicaciones que se ejecutan en él).
fuente
Básicamente, el problema es que la implementación de TCP no sabe qué hará la aplicación a continuación. Cuando la aplicación del servidor realiza una secuencia de escrituras, la pila no sabe si las escrituras que ha recibido hasta ahora son la secuencia completa o solo una parte de ella.
La mayoría de las veces, la aplicación del servidor hace que las escrituras en el búfer sean más rápidas de lo que la pila de red puede vaciarlo. Entonces el búfer está lleno y salen paquetes de tamaño completo.
Pero a veces algo más ralentiza la aplicación del servidor. Tal vez esperando que se lea un disco en una matriz de discos sobrecargados o algo así. Por lo tanto, el búfer se vacía y la pila de red tiene que elegir entre enviar un paquete más pequeño (más sobrecarga) o esperar datos que tal vez nunca lleguen (agregando retraso).
fuente
Si observa el cuadro 34, verá que el servidor ha transmitido un búfer de 32kB y que el bit PSH está configurado. Si observa 82, verá lo mismo, 32 kB del bit PSH anterior. El paquete 52 tiene un bit PSH a pesar de que ha habido menos de 2kB de la respuesta.
El bit PSH generalmente lo establece una pila TCP para el último segmento de una PDU de aplicación escrita en la red. Entonces, la aplicación usa un búfer de 32kB y cuando hay muchos datos, los escribe en el socket TCP de 32kB a la vez. Cuando hay menos datos como en los cuadros 51-52, es porque la aplicación escribió ese registro primero en la respuesta y solo tenía 1820 bytes.
Tenga en cuenta que la aplicación a la que me refiero puede, de hecho, no ser la aplicación del servidor en sí, sino algún software intermedio, como una máquina virtual Java (JVM) o lo que sea. No está claro por el contenido de los datos por qué se envió esa PDU de 1820 bytes, ¿tal vez un búfer de 32kB no estaba disponible en ese momento?
El punto es que no debería importar, no hay una penalización de rendimiento sustancial.
fuente