"La aplicación ha funcionado bien durante años, la semana pasada la red se actualizó y pasamos de 100 mbps a gigabit. Ahora la última mitad de los datos de algunos mensajes es basura. La gente de la red jura que no es la red - pero eso es lo único que cambió."
La buena noticia es que la costosa actualización de la red no rompió la aplicación.
La mala noticia es que la aplicación está rota y siempre lo ha estado. 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 que la envía envíe dos segmentos TCP de 1000 bytes. Los mensajes de la aplicación pueden ser segmentados en piezas más pequeñas basándose en el tamaño máximo de segmento anunciado por el receptor o en 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 proporcione a la aplicación receptora dos mensajes de 1000 bytes. Por ejemplo, si el búfer de la aplicación es sólo de 500 bytes, eso es todo lo que la pila TCP devolverá. Por otro lado, si el buffer es de 1500 bytes y ambos segmentos de 1000 bytes han llegado, 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 en mensajes.
¿Qué tiene que ver esto con la actualización de la red? Bueno, el servidor OpenVOS y el cliente Linux estaban en diferentes subredes, así que el sistema OpenVos estaba anunciando un tamaño máximo de segmento de 536 bytes. Los mensajes de la aplicación enviados por el cliente eran de 1000 bytes, así que los mensajes se segmentaron 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. Después de la actualización, la sincronización del segmento cambió de manera que parte del tiempo sólo el primer segmento estaba disponible cuando la aplicación publicó su recepción. Los últimos 464 (1000 - 536) bytes del buffer de la aplicación no fueron rellenados por la pila TCP y contenían cualquier basura que hubiera antes de que la recepción fuera contabilizada.
En este caso hubo una solución rápida fácil, aumentar el valor del MSS anunciado de OpenVOS a 1460 (ver Una forma fácil de mejorar el rendimiento del TCP en las subredes). Sin embargo, esto es en realidad sólo una brecha de parada. La verdadera solución será reescribir el código para analizar correctamente el flujo de bytes TCP en los mensajes de la aplicación en lugar de asumir que una llamada de recepción devolverá un mensaje.