TCP O tamanho da janela aumenta drasticamente e o remetente não envia até que o buffer de recebimento não esteja vazio

3

Eu tenho um fluxo de download sobre TCP em um aplicativo (em execução no Win2k12).
O problema é que a conexão é fechada pelo remetente porque expira.

Eu usei o wireshark para ver o que acontece em dois servidores diferentes (em um servidor ele funciona bem, por outro, o tempo é esgotado). Eu notei o mesmo comportamento em ambos: Quando o download começa, tudo parece ok, o tamanho da janela é de 64k e permanece o mesmo por algum tempo, segmentos são reconhecidos. Então, em algum momento, o tamanho da janela começa a diminuir até que seja 0. (Até onde eu sei, o receptor não consegue acompanhar o remetente.) No entanto, não há mensagem de confirmação ACK ou de janela do receptor até buffer inteiro é lido pelo aplicativo, então uma atualização do Windows anuncia o tamanho da janela de 64k novamente. Então começa de novo. O tamanho da janela diminui até zero.
Isso não parece certo para mim. Como o aplicativo lê o buffer, ele deve ter espaço livre e uma atualização do Windows deve ser enviada, para que o remetente possa enviar o próximo segmento.

A outra coisa que não entendo é o comportamento no servidor com falha. Este servidor anuncia tamanhos de janela maiores e maiores em cada ciclo, no último ciclo antes do tempo limite o tamanho da janela era ~ 800 000. O tempo limite ocorre porque o buffer não é esvaziado rápido o suficiente. Mas eu não tenho idéia porque o tamanho da janela está aumentando neste servidor? Existe uma configuração no servidor para evitar isso?

As minhas suposições estão corretas ou eu entendi mal algo sobre o protocolo TCP? Qualquer ideia para resolver este problema é apreciada.

Obrigado.

    
por Andras Toth 25.04.2014 / 12:41

1 resposta

1

Se o processo de recebimento não estiver processando dados tão rápido quanto eles podem ser transferidos pela rede, a janela deverá ficar menor à medida que os pacotes forem recebidos até que o buffer de recebimento esteja cheio e a janela seja 0. O servidor ainda está supostamente para ACK os dados recebidos nesta situação, de tal forma que o remetente sabe não retransmiti-lo.

Quando a janela for para 0, a extremidade receptora não deve anunciar que há espaço na janela para mais dados imediatamente após o aplicativo ler outro byte do fluxo. Deve pelo menos esperar até que haja espaço livre suficiente para corresponder a um pacote com tamanho de MTU. Esperar muito mais que isso não é uma boa ideia.

Redimensionar dinamicamente a alocação de memória durante a transferência é um comportamento sensato. No entanto, o algoritmo deve procurar convergir em um tamanho que seja grande o suficiente para não causar um gargalo, mas não deve ser muito maior do que isso. Flutuação do jeito que você descreve, não deveria estar acontecendo. E se o aplicativo de recebimento não conseguir acompanhar os dados que chegam, o tamanho da janela não deve ser aumentado.

O remetente não deve expirar a conexão sem enviar alguns pacotes de manutenção primeiro. Se o remetente expirar a conexão sem enviar pacotes keep-alive, então eu diria que há um bug no remetente. Se o remetente enviar pacotes keep-alive, mas o receptor não responder a eles, então eu diria que há um bug no receptor.

Você inspecionou a comunicação de cada extremidade da conexão para garantir que não haja queda significativa de pacotes causando o tempo limite?

    
por 29.04.2014 / 22:25