Rozmiary pakietów w strumieniu TCP

10

Jestem ruchem sieciowym i chcę podzielić każdą sesję TCP na serię żądań i odpowiedzi (protokoły, nad którymi pracuję, działają w ten sposób, np. HTTP lub SSL).

Miałem proste założenie (ignorowanie nieporządku i ponowne wysyłanie pakietów) - biorąc pod uwagę fragment danych, które należy wysłać, zostaną one wysłane przy użyciu możliwie największych pakietów, a ostatni pakiet będzie albo mniejszy niż maksymalny rozmiar, albo będzie śledzony przez pakiet z drugiej strony (ignorowanie pustych pakietów ACK). Tak więc w sesji HTTP oczekuję, że zobaczę coś takiego (ponownie, bez uwzględnienia acks) -

Pakiet 1 - Poproś o „Get ...”

Pakiet 2 - Odpowiedź, rozmiar 1434

Pakiet 3 - Odpowiedź, rozmiar 1434

Pakiet 4 - Odpowiedź, rozmiar 1434

Pakiet 5 - Odpowiedź, rozmiar 500

Tak się dzieje na większości sesji, jednak widziałem przynajmniej jedną okazję, która wyglądała

Pakiet 1 - Poproś o „Get ...”

Pakiet 2 - Odpowiedź, rozmiar 1434

Pakiet 3 - Odpowiedź, rozmiar 1080

Pakiet 4 - Odpowiedź, rozmiar 1434

Pakiet 5 - Odpowiedź, rozmiar 500

Brak retransmisji, pakiety poza kolejnością lub wyjątkowe opóźnienia na serwerze.

Chcę wiedzieć - co może to spowodować i kiedy to nastąpi? Jak błędne jest moje założenie?

AKTUALIZACJA

I umieścić plik przykład pcap tutaj

AKTUALIZACJA 2

W tym tsharkzrzut z odpowiednimi polami ...

$ 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
źródło
Powodów może być tak wiele ... Rozmiar okna może być zbyt mały (choć w twoim przypadku bardzo mało prawdopodobny), może nie być wystarczającej ilości danych do wysłania (czy dane wyjściowe są generowane przez skrypt?), Oprogramowanie generujące dane może wyraźnie go
spłukali
@SanderSteffann, rozmiar okna nie wydaje się istotny, pakiety pojawiają się w dość regularnych odstępach czasu. Cała odpowiedź jest javascript, więc nie sądzę, że jest generowany przez inny skrypt.
Vadim
@vadim, czy mógłbyś zamieścić zrzut ekranu lub lepiej, hiperłącze do pcap z ładunkiem 1080 bajtów?
Mike Pennington,
@MikePennington - dziękuję za twój wkład, podam link do pliku pcap za kilka godzin.
Vadim,
@MikePennington - dodałem link do pliku pcap, który to pokazuje.
Vadim

Odpowiedzi:

6

Warstwa TCP wykorzystuje algorytm Nagle do buforowania ruchu (wysyła mniej dużych pakietów, zamiast więcej małych pakietów ... co czyni go bardziej wydajnym); aplikacja może powiedzieć „wyślij ją teraz”. Widzisz to w nagłówku TCP z flagą zwaną bitem PSH (push). Podczas gdy bit jest ustawiany przez stos, wypychanie odbywa się na żądanie aplikacji.

To jest zamierzone i normalne zachowanie.

Fredpbaker
źródło
Wyjaśnienie ... Aplikacje nie mają bezpośredniej kontroli nad bitem PSH ...
Mike Pennington
Całkiem słusznie, było to, co miało być zrobione w oryginalnym RFC i co zrobiono
Winsock
po spojrzeniu na pcap jest bardzo mało prawdopodobne, aby serwer WWW ustawił PSH na ruch PO
Mike Pennington
3

Rozmiar pakietu zależy od tego, jak aplikacja i / lub system operacyjny buforuje i wysyła dane sieciowe. Jeśli aplikacja i / lub system operacyjny zdecydują się wysłać dane po tym, jak w buforze znajdzie się 1080 bajtów, pakiet będzie miał 1080 bajtów (plus nagłówki). Może to być wiele powodów. W twoim przypadku musisz zajrzeć do kodu źródłowego serwera WWW i / lub stosu sieciowego systemu operacyjnego.

Sebastian Wiesinger
źródło
Widzę wiele pakietów o maksymalnym rozmiarze i tylko ten o mniejszym rozmiarze, więc nie jest to żadna domyślna wartość. Czy mógł to być czkawka serwera - utknął na czymś innym z powodu opóźnienia, które wystarczyło, aby stos sieci zdecydował o wysłaniu zawartości bufora?
Vadim
Jasne, mogło być cokolwiek. Nie można tego stwierdzić bez debugowania serwera i systemu operacyjnego, na którym działa. Ale nie ma się czym przejmować IMHO.
Sebastian Wiesinger
Nie jestem zaniepokojony, po prostu wydawało mi się to dziwne i chciałem dowiedzieć się, czy jest w tym coś więcej.
Vadim
1
Jeśli wireshark szuka w nagłówku TCP pakietów 1080 1080 dla bitu PSH (push). To jest stos aplikacji z informacją, że wyślij teraz te dane.
fredpbaker
1
Patrz wyżej, w większości przypadków jest to stos TCP
fredpbaker
1

Rozmiar pakietu jest definiowany przez system operacyjny (ogólnie) i jest związany z buforami, ilością danych dostarczanych przez aplikację itp. Wiele strategii można wykorzystać w celu osiągnięcia maksymalnej wydajności, a czasami wysyłanie mniejszych pakietów może być szybsze niż oczekiwanie na utworzenie większy pakiet.

Czasami liczba uruchomionych aplikacji może wymagać szybszego działania systemu operacyjnego (wysyłanie tego, co do tej pory było w buforze) zamiast nasycania bufora.

Być może możesz podać nam więcej szczegółów na temat scenariusza, z którym pracujesz (np .: system operacyjny serwera, uruchomione na nim aplikacje).

woliveirajr
źródło
0

Zasadniczo problem polega na tym, że implementacja TCP nie wie, co aplikacja zrobi dalej. Kiedy aplikacja serwera wykonuje sekwencję zapisów, stos nie wie, czy dotychczas otrzymane zapisy stanowią całą sekwencję, czy tylko jej część.

Przez większość czasu aplikacja serwera zapisuje do bufora szybciej niż stos sieciowy jest w stanie go opróżnić. Bufor jest pełny i wychodzą pełnowymiarowe pakiety.

Ale czasami coś innego spowalnia aplikację serwera. Może czekanie na odczyt dysku na przeciążonej macierzy dyskowej lub coś w tym rodzaju. Bufor opróżnia się, a stos sieciowy musi wybierać między wysyłaniem mniejszego pakietu (większy narzut) lub czekaniem na dane, które mogą nigdy nie nadejść (dodanie opóźnienia).

Peter Green
źródło
0

Jeśli spojrzysz na ramkę 34, zobaczysz, że serwer przesłał bufor 32kB i że bit PSH jest ustawiony. Jeśli spojrzysz na 82, zobaczysz to samo, 32 kB z poprzedniego bitu PSH. Pakiet 52 ma bit PSH, mimo że odpowiedź była mniejsza niż 2 kB.

Bit PSH jest zwykle ustawiany przez stos TCP dla ostatniego segmentu PDU aplikacji zapisanego w sieci. Dlatego aplikacja używa bufora 32kB, a gdy jest dużo danych, zapisuje je jednocześnie do gniazda TCP 32kB. Kiedy danych jest mniej niż w ramkach 51-52, dzieje się tak dlatego, że aplikacja zapisała ten rekord jako pierwszy w odpowiedzi i miał on tylko 1820 bajtów.

Zauważ, że aplikacja, o której mówię, może w rzeczywistości nie być samą aplikacją serwera, ale jakimś oprogramowaniem pośrednim, takim jak Java Virtual Machine (JVM) lub czymkolwiek. Z treści danych nie wynika jasno, dlaczego wysłano PDU o wielkości 1820 bajtów, być może bufor 32kB nie był wtedy dostępny?

Chodzi o to, że nie powinno to mieć znaczenia, nie ma istotnej kary za wydajność.

marctxk
źródło