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 tshark
despejo 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
Respostas:
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.
fonte
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.
fonte
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).
fonte
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).
fonte
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.
fonte