Tamanhos de pacotes em um fluxo TCP

10

Sou tráfego de rede e desejo dividir cada sessão TCP em uma série de solicitações e respostas (os protocolos com os quais estou trabalhando funcionam dessa maneira, como HTTP ou SSL).

Eu tinha uma suposição simples (ignorando pacotes fora de ordem e reenviando) - dado um pedaço de dados que precisa ser enviado, eles serão enviados usando os maiores pacotes possíveis e o último pacote será menor que o tamanho máximo ou será seguido por um pacote do outro lado (ignorando pacotes vazios de ACK). Então, em uma sessão HTTP, espero ver algo como (novamente, desconsiderando o acks) -

Pacote 1 - Solicite "Obter ..."

Pacote 2 - Resposta, tamanho 1434

Pacote 3 - Resposta, tamanho 1434

Pacote 4 - Resposta, tamanho 1434

Pacote 5 - Resposta, tamanho 500

Qual é o que eu recebo na maioria das sessões, mas há pelo menos uma ocasião que eu vi que parecia

Pacote 1 - Solicite "Obter ..."

Pacote 2 - Resposta, tamanho 1434

Pacote 3 - resposta, tamanho 1080

Pacote 4 - Resposta, tamanho 1434

Pacote 5 - Resposta, tamanho 500

Sem retransmissões, pacotes com defeito aqui ou atrasos excepcionais no servidor.

Eu quero saber - o que pode causar isso e quando ocorrerá? Quão errada é minha suposição?

ATUALIZAR

Eu coloquei um exemplo de arquivo pcap aqui

ATUALIZAÇÃO 2

Incluindo um tsharkdespejo com campos relevantes ...

$ tshark -r http_1082.pcap -T fields -e frame.number -e frame.len \
    -e ip.src -e ip.dst -e tcp.flags.push -e http.request.method \
    -e http.request.uri -e http.response.code | head -n 47
1     66      192.168.1.103    206.33.49.126    0            
2     62      206.33.49.126    192.168.1.103    0            
3     64      192.168.1.103    206.33.49.126    0            
4     411     192.168.1.103    206.33.49.126    1    GET    /money/.element/script/3.0/video/xmp/xmp_playlistapi.js    
5     54      206.33.49.126    192.168.1.103    0            
6     1434    206.33.49.126    192.168.1.103    0            
7     1434    206.33.49.126    192.168.1.103    0            
8     64      192.168.1.103    206.33.49.126    0            
9     1434    206.33.49.126    192.168.1.103    0            
10    1434    206.33.49.126    192.168.1.103    0            
11    1434    206.33.49.126    192.168.1.103    0            
12    64      192.168.1.103    206.33.49.126    0            
13    1434    206.33.49.126    192.168.1.103    0            
14    1434    206.33.49.126    192.168.1.103    0            
15    1434    206.33.49.126    192.168.1.103    0            
16    1434    206.33.49.126    192.168.1.103    0            
17    64      192.168.1.103    206.33.49.126    0            
18    1434    206.33.49.126    192.168.1.103    0            
19    1434    206.33.49.126    192.168.1.103    0            
20    1434    206.33.49.126    192.168.1.103    0            
21    1434    206.33.49.126    192.168.1.103    0            
22    1434    206.33.49.126    192.168.1.103    0            
23    64      192.168.1.103    206.33.49.126    0            
24    1434    206.33.49.126    192.168.1.103    0            
25    1434    206.33.49.126    192.168.1.103    0            
26    1434    206.33.49.126    192.168.1.103    0            
27    1434    206.33.49.126    192.168.1.103    0            
28    1434    206.33.49.126    192.168.1.103    0            
29    1434    206.33.49.126    192.168.1.103    0            
30    64      192.168.1.103    206.33.49.126    0            
31    1434    206.33.49.126    192.168.1.103    0            
32    1434    206.33.49.126    192.168.1.103    0            
33    1434    206.33.49.126    192.168.1.103    0            
34    1082    206.33.49.126    192.168.1.103    1     <------ Packet in question        
35    1434    206.33.49.126    192.168.1.103    0            
36    1434    206.33.49.126    192.168.1.103    0            
37    1434    206.33.49.126    192.168.1.103    0            
38    64      192.168.1.103    206.33.49.126    0            
39    1434    206.33.49.126    192.168.1.103    0            
40    1434    206.33.49.126    192.168.1.103    0            
41    1434    206.33.49.126    192.168.1.103    0            
42    1434    206.33.49.126    192.168.1.103    0            
43    1434    206.33.49.126    192.168.1.103    0            
44    1434    206.33.49.126    192.168.1.103    0            
45    1434    206.33.49.126    192.168.1.103    0            
46    626     206.33.49.126    192.168.1.103    1            200
47    64      192.168.1.103    206.33.49.126    0 
Vadim
fonte
Pode haver muitas razões ... O tamanho da janela pode ser muito pequeno (embora seja improvável no seu caso), pode não haver dados suficientes para enviar (a saída é gerada por um script?), O software que gera os dados pode ter liberado explicitamente, etc.
Sander Steffann
@SanderSteffann, o tamanho da janela não parece relevante, as críticas vêm em intervalos bastante regulares. Toda a resposta é um javascript, então não acho que seja gerado por outro script.
Vadim
@adim, você poderia postar uma captura de tela ou, melhor, um hiperlink para o pcap com a carga útil de 1080 bytes?
Mike Pennington
@ MikePennington - obrigado pela sua contribuição, fornecerei um link para o arquivo pcap em várias horas.
Vadim
@ MikePennington - adicionei um link para um arquivo pcap que demonstra isso.
Vadim

Respostas:

6

A camada TCP usa o algoritmo Nagle para armazenar tráfego (ele envia menos pacotes grandes, em vez de mais pacotes pequenos ... tornando-o mais eficaz); existe uma maneira de o aplicativo dizer 'envie agora'. Você vê isso no cabeçalho TCP com um sinalizador chamado bit PSH (push). Enquanto o bit é definido pela pilha, o envio é feito a pedido do aplicativo.

Portanto, esse é o comportamento pretendido e normal.

fredpbaker
fonte
Ponto de esclarecimento ... Applications não tem controle direto sobre o bit PSH ...
Mike Pennington
Muito bem, havia que deveria ser feito no RFC original e que foi feito winsock e tomadas
fredpbaker
depois de olhar para o pcap, é muito improvável que o PSH conjunto webserver relativos ao tráfego do OP
Mike Pennington
3

O tamanho do pacote depende de como o aplicativo e / ou o SO armazenam buffer e envia dados da rede. Se o aplicativo e / ou o sistema operacional decidir enviar os dados depois que 1080 bytes estiverem no buffer, o pacote terá 1080 bytes (mais cabeçalhos). Pode haver muitas razões para isso. No seu caso, você precisaria procurar o código-fonte do servidor da web e / ou a pilha de rede do sistema operacional.

Sebastian Wiesinger
fonte
Vejo muitos pacotes com tamanho máximo e apenas este com tamanho menor, portanto não é um tipo padrão. Poderia ter sido um problema de servidor - estava preso a outra coisa por um atraso suficiente para a pilha de rede decidir enviar o que estava no buffer?
Vadim
Claro, poderia ter sido qualquer coisa. Não há como saber sem depurar o servidor e o sistema operacional em que está sendo executado. Mas não há nada para se alarmar com o IMHO.
Sebastian Wiesinger
Não estou alarmado, parecia estranho e queria descobrir se há mais do que isso.
Vadim
11
Se você possui o wireshark, procure no cabeçalho TCP de 1080 pacotes o bit PSH (push). Essa é a pilha de aplicativos dizendo para enviar esses dados agora.
Fredpbaker 31/08
11
Veja acima, é a pilha TCP na maioria dos casos
fredpbaker
1

O tamanho do pacote é definido pelo sistema operacional (em geral) e está relacionado a buffers, quantidade de dados fornecidos pelo aplicativo etc. Muitas estratégias podem ser usadas para alcançar o desempenho máximo e, às vezes, enviar pacotes menores pode ser mais rápido do que esperar para criar um pacote maior.

Às vezes, a quantidade de aplicativos em execução pode exigir que o sistema operacional seja mais rápido (envie o que tiver no buffer até o momento), em vez de saturar o buffer.

Talvez você possa nos fornecer mais detalhes sobre o cenário em que estava trabalhando (por exemplo: sistema operacional do servidor, aplicativos em execução).

woliveirajr
fonte
0

Fundamentalmente, o problema é que a implementação do TCP não sabe o que o aplicativo fará a seguir. Quando o aplicativo do servidor faz uma sequência de gravações, a pilha não sabe se as gravações que recebeu até agora são a sequência inteira ou apenas parte dela.

Na maioria das vezes, o aplicativo do servidor faz gravações no buffer mais rapidamente do que a pilha de rede é capaz de esvaziá-lo. Portanto, o buffer está cheio e saem pacotes de tamanho normal.

Mas, às vezes, algo mais torna o aplicativo do servidor lento. Talvez aguardando a leitura de um disco em uma matriz de disco sobrecarregada ou algo assim. Portanto, o buffer esvazia e a pilha de rede precisa escolher entre enviar um pacote menor (mais sobrecarga) ou aguardar dados que talvez nunca venham (adicionando atraso).

Peter Green
fonte
0

Se você observar o quadro 34, verá que o servidor transmitiu um buffer de 32kB e que o bit PSH está definido. Se você olhar para 82, verá o mesmo, 32 kB do bit PSH anterior. O pacote 52 possui um bit PSH, embora tenha havido menos de 2kB da resposta.

O bit PSH é normalmente definido por uma pilha TCP para o último segmento de uma PDU de aplicativo gravada na rede. Portanto, o aplicativo usa um buffer de 32kB e, quando há muitos dados, os grava no soquete TCP de 32kB por vez. Quando há menos dados como nos quadros 51-52, é porque o aplicativo escreveu esse registro primeiro na resposta e eram apenas 1820 bytes.

Observe que o aplicativo a que me refiro de fato pode não ser o aplicativo do servidor, mas algum software intermediário, como uma Java Virtual Machine (JVM) ou qualquer outra coisa. Não está claro no conteúdo dos dados por que a PDU de 1820 bytes foi enviada, talvez um buffer de 32kB não estivesse disponível no momento?

O ponto é que isso não deve importar, não há penalidade substantiva no desempenho.

marctxk
fonte