Ir al contenido principal
«La aplicación ha funcionado bien durante años; la semana pasada se actualizó la red y pasamos de 100 Mbps a gigabit. Ahora, la última mitad de los datos de algunos mensajes es basura. Los responsables de la red juran que no es culpa de la red, pero eso es lo único que ha cambiado».

 

La buena noticia es que la costosa actualización de la red no ha afectado al funcionamiento de la aplicación.

 

La mala noticia es que la aplicación no funciona y nunca ha funcionado. Lo que *muchas* personas que escriben aplicaciones TCP no se dan cuenta es que TCP es un flujo de bytes, no de mensajes. El hecho de que una aplicación envíe dos mensajes de 1000 bytes no significa que la pila TCP emisora vaya a enviar dos segmentos TCP de 1000 bytes. Los mensajes de la aplicación pueden segmentarse en partes más pequeñas en función del tamaño máximo de segmento anunciado por el receptor o de alguna limitación de configuración del emisor. Las retransmisiones también pueden combinar y fragmentar los mensajes de la aplicación. Incluso si la pila TCP emisora envía realmente dos segmentos TCP de 1000 bytes, no hay garantía de que la pila TCP receptora vaya a entregar a la aplicación receptora dos mensajes de 1000 bytes. Por ejemplo, si el búfer de la aplicación es de solo 500 bytes, eso es todo lo que devolverá la pila TCP. Por otro lado, si el búfer es de 1500 bytes y han llegado ambos segmentos de 1000 bytes, la pila TCP devolverá 1500 bytes en la primera llamada y 500 en la segunda. Depende de la aplicación tomar el flujo de bytes y analizarlo correctamente para convertirlo de nuevo en mensajes.

 

¿Qué tiene esto que ver con la actualización de la red? Pues bien, el servidor OpenVOS y el cliente Linux se encontraban en subredes diferentes, por lo que el sistema OpenVOS anunciaba un tamaño máximo de segmento de 536 bytes. Los mensajes de la aplicación enviados por el cliente tenían 1000 bytes, por lo que los mensajes se segmentaban en dos partes. Antes de la actualización, parece que ambos segmentos llegaban al servidor OpenVOS antes de que la aplicación publicara su recepción, por lo que los 1000 bytes se leían con una sola llamada a la función de recepción. Tras la actualización, la sincronización de los segmentos cambió, de modo que, en algunas ocasiones, solo el primer segmento estaba disponible cuando la aplicación publicaba su recepción. Los últimos 464 (1000 – 536) bytes del búfer de la aplicación no eran rellenados por la pila TCP y contenían cualquier residuo que hubiera allí antes de que se enviara la recepción.

 

En este caso, había una solución rápida y sencilla: aumentar el valor MSS anunciado por OpenVOS a 1460 (véase «Una forma sencilla de mejorar el rendimiento de TCP entre subredes»). Sin embargo, eso no es más que un parche temporal. La solución real consistirá en reescribir el código para analizar correctamente el flujo de bytes TCP y convertirlo de nuevo en mensajes de aplicación, en lugar de limitarse a suponer que una llamada de recepción devolverá un mensaje.