"A aplicação está funcionando bem há anos, na semana passada a rede foi atualizada e passamos de 100 mbps para gigabit". Agora, a última metade dos dados em algumas mensagens é lixo. As pessoas da rede juram que não é a rede - mas isso é a única coisa que mudou".
A boa notícia é que a dispendiosa atualização da rede não quebrou a aplicação.
A má notícia é que o pedido está quebrado e sempre foi quebrado. O que *pessoas* que escrevem aplicações TCP não percebem é que o TCP é um fluxo de bytes, não de mensagens. O fato de uma aplicação enviar duas mensagens de 1000 bytes não significa que a pilha TCP de envio enviará dois segmentos TCP de 1000 bytes. As mensagens da aplicação podem ser segmentadas em partes menores com base no tamanho máximo do segmento anunciado pelo receptor ou em alguma limitação de configuração do remetente. As retransmissões também podem combinar e fragmentar as mensagens de aplicação. Mesmo que a pilha TCP de envio envie realmente dois segmentos TCP de 1000 bytes, não há garantia de que a pilha TCP de recepção dará à aplicação receptora duas mensagens de 1000 bytes. Por exemplo, se o buffer da aplicação é de apenas 500 bytes, toda a pilha TCP retornará. Por outro lado, se o buffer for de 1500 bytes e ambos os segmentos de 1000 bytes tiverem chegado, a pilha TCP retornará 1500 bytes na primeira chamada e 500 na segunda. Cabe ao aplicativo pegar o fluxo de bytes e analisá-lo corretamente de volta às mensagens.
O que isso tem a ver com a atualização da rede? Bem, o servidor OpenVOS e o cliente Linux, onde em diferentes sub-redes o sistema OpenVos estava anunciando um tamanho máximo de segmento de 536 bytes. As mensagens da aplicação enviadas pelo cliente eram de 1000 bytes, então as mensagens estavam sendo segmentadas em 2 partes. Antes da atualização, parece que ambos os segmentos estavam chegando ao servidor OpenVOS antes de a aplicação anunciar sua recepção, de modo que todos os 1000 bytes foram lidos com uma chamada para a função de recepção. Após o upgrade, o tempo do segmento mudou de forma que, em parte do tempo, somente o primeiro segmento estava disponível quando a aplicação postou seu recebimento. Os últimos 464 (1000 - 536) bytes do buffer da aplicação não foram preenchidos pela pilha TCP e continham o lixo que estava lá antes de a recepção ser postada.
Neste caso, houve uma correção rápida e fácil, aumentar o valor do MSS anunciado pelo OpenVOS para 1460 (veja Uma maneira fácil de melhorar a taxa de transferência TCP através de sub-redes). Isso, entretanto, é realmente apenas uma lacuna de parada. A verdadeira solução será reescrever o código para analisar corretamente o fluxo de bytes TCP nas mensagens da aplicação em vez de apenas assumir que 1 chamada recebida retornará 1 mensagem.