Pular para o conteúdo principal

Um equívoco comum é que o TCP garante a entrega dos dados. O que o TCP realmente garante é que ele entregará os dados para a pilha TCP do host receptor ou relatará um erro para o aplicativo de envio. Infelizmente, o relatório de erro não indica a quantidade de dados que foi realmente entregue. Há também uma diferença significativa entre a pilha TCP do receptor e a aplicação receptora.

Há dois cenários básicos de falha. No primeiro, a pilha TCP de envio não está recebendo reconhecimentos TCP para os dados que está transmitindo. Neste cenário, a aplicação de envio pode continuar a chamar o send para colocar mais dados no buffer de envio da pilha TCP. Uma vez que o TCP stack expira a transmissão, o próximo envio (ou recebimento) chamado pelo aplicativo de envio indicará o erro ETIMEDOUT. A aplicação agora sabe que houve um problema, mas não tem idéia de quantos dados foram transmitidos com sucesso. O sucesso significa que a pilha TCP de envio recebeu um reconhecimento para os dados da pilha TCP de recebimento.

No segundo cenário, a pilha TCP de envio transmite dados e recebe um reset ao invés de um reconhecimento. O reset pode indicar que a pilha TCP receptora fechou o soquete ou algum dispositivo de rede, talvez um firewall, foi temporizado. A próxima vez que o aplicativo de envio de chamadas enviar (ou receber) o erro ECONNRESET é indicado. Você pode pensar que neste cenário o aplicativo de envio poderia inferir que foram apenas os dados da última chamada de envio que falharam, mas você estaria errado. É possível que a pilha TCP de envio tenha armazenado os dados de várias chamadas de envio em um segmento TCP e que esse segmento tenha acionado o reset ou que uma série de segmentos TCP tenham sido enviados antes do reset, acionado pelo primeiro segmento da série, tenha chegado de volta ao remetente. Tudo o que a aplicação de envio pode inferir é que nem todos os dados foram transmitidos com sucesso.

Há um terceiro cenário de falha que nada tem a ver com a pilha TCP (envio ou recebimento) ou com a rede. Assumir que o aplicativo receptor tem um bug que o impede de ler os dados. A pilha TCP receptora continuará recebendo os dados e enviando confirmações TCP até o ponto em que o TCP receber o buffer de preenchimento. No entanto, isso pode ser de até 64K bytes de dados (ou mais se a escala da janela TCP for suportada). Se a aplicação receptora precisar ser reiniciada, todos os dados no buffer de recepção TCP serão perdidos. A pilha TCP receptora deve (mas não pode) enviar um reset para a pilha TCP emissora quando a aplicação receptora for encerrada. Ele enviará um reset na próxima vez em que receber um segmento para a conexão agora fechada. Do ponto de vista da aplicação de envio, isto é semelhante ao segundo cenário. Entretanto, aponta que mesmo que a pilha TCP receptora reconheça os dados, no caso de um erro, não é seguro para o remetente assumir que a aplicação receptora leu os dados.

A idéia de retirar destes cenários de falha é que sem um reconhecimento da camada de aplicação, um tempo limite de transmissão ou erro de reset indica que alguns, possivelmente todos os dados transmitidos podem não ter sido lidos pela aplicação receptora. Por este motivo, recomendo que todas as aplicações incluam reconhecimentos na camada de aplicação, estejam preparadas para restabelecer uma conexão e retransmitir dados não reconhecidos e sejam capazes de lidar com dados duplicados, já que o que pode ter sido perdido é o reconhecimento.

© 2020 Stratus Technologies.