Transport

Kontrola Przepływu TCP

Mechanizm przesuwnego okna i kontrola przepływu w połączeniach TCP.

Wprowadzenie: Różnica Między Tempem Nadawania a Odbioru

Kontrola przepływu w TCP odpowiada na różnicę między tempem wytwarzania danych przez nadawcę a tempem ich odbioru. Odbiorca przechowuje napływające bajty w buforze odbiorczym i ogłasza dostępną pojemność. Nadawca wykorzystuje tę informację do ograniczenia liczby niepotwierdzonych danych i uniknięcia przekroczenia wolnego miejsca po stronie odbiorcy.

Kontrola przepływu w TCP dotyczy różnicy między szybkością wysyłania i przetwarzania danych. Komputer wysyłający może generować i wysyłać dane znacznie szybciej, niż komputer odbierający może je przetworzyć. Serwer może transmitować dane z prędkością gigabitów na sekundę, podczas gdy smartfon lub starszy laptop wykonuje inne zadania i nie nadąża z ich odbiorem.

Bez kontroli szybki nadawca zapełniłby bufor odbiorcy. Dane przychodzące po jego zapełnieniu trzeba byłoby odrzucić, co prowadziłoby do utraty segmentów, retransmisji i spadku wydajności połączenia. Kontrola Przepływu w TCP pozwala odbiorcy informować nadawcę, ile danych może przyjąć w danym momencie. Nadawca ogranicza wtedy liczbę niepotwierdzonych danych do ogłoszonego okna odbiorczego. Mechanizm ten chroni przed przepełnieniem bufora. Jest odrębny od kontroli przeciążenia, która ogranicza wysyłanie z powodu stanu sieci.

Główne Komponenty Kontroli Przepływu

Kontrola przepływu w TCP opiera się na dwóch komponentach działających razem: tymczasowym obszarze przechowywania po stronie odbiorcy i mechanizmie komunikacyjnym w nagłówku TCP do zarządzania tym obszarem.

1. Bufor Odbiorczy TCP

Dla każdego połączenia TCP system operacyjny odbiorcy przydziela blok pamięci zwany buforem odbiorczym. Bufor ten działa jak tymczasowy obszar przechowywania przychodzących danych. Gdy segmenty TCP docierają, ich dane są umieszczane w tym buforze. Aplikacja działająca na odbiorcy (np. przeglądarka internetowa lub klient e-mail) odczytuje dane z tego bufora we własnym tempie.

Bufor odbiorczy przechowuje dane segmentów do czasu ich odczytania przez aplikację. Sieć dostarcza segmenty, a aplikacja pobiera dane w swoim tempie. Kontrola przepływu ogranicza ilość danych przekazywanych do bufora. Ilość wolnego miejsca jest informacją, którą odbiorca przekazuje nadawcy.

2. Pole Okna Odbiorczego (rwnd)

Komunikacja o ilości miejsca w buforze odbywa się za pośrednictwem pola Rozmiar Okna (często nazywanego Oknem Odbiorczym lub 'rwnd') w . To 16-bitowe pole pozwala odbiorcy ogłosić, ile ma aktualnie dostępnego miejsca w swoim buforze odbiorczym, w bajtach.

ACK może przenosić aktualnie ogłoszoną wartość 'rwnd'. Na przykład, jeśli bufor ma pojemność 64 KiB, a 10 KiB danych oczekuje w nim na odczytanie przez aplikację, odbiorca ogłosi 'rwnd' równe 54 KiB. Nadawca może wtedy wysłać najwyżej 54 KiB nowych danych, zanim otrzyma kolejną aktualizację. Wartość okna tworzy sprzężenie zwrotne, które dopasowuje ilość danych w tranzycie do wolnego miejsca po stronie odbiorcy.

Wyjaśnienie Mechanizmu Przesuwnego Okna

Proces zarządzania transmisją danych na podstawie ogłoszonego rozmiaru okna odbiorczego nazywany jest mechanizmem przesuwnego okna. Pozwala on utrzymywać wiele niepotwierdzonych bajtów w tranzycie, więc nadawca nie musi czekać na potwierdzenie każdego segmentu przed wysłaniem następnego.

Okno jest koncepcyjnym zakresem numerów sekwencyjnych, które nadawca ma obecnie prawo przesłać. W miarę wysyłania i potwierdzania danych, to okno przesuwa się do przodu wzdłuż przestrzeni numerów sekwencyjnych całego strumienia danych.

Terminologia Okna (Strona Nadawcy)

Zdefiniujmy kilka zmiennych, które nadawca śledzi dla swojego okna wysyłania:

  • Ostatni Wysłany Bajt (LBS): Numer sekwencyjny ostatniego bajtu danych, który został wysłany.
  • Ostatni Potwierdzony Bajt (LBA): Numer sekwencyjny ostatniego bajtu danych, który odbiorca pomyślnie potwierdził. Wszystkie bajty przed nim uważa się za pomyślnie dostarczone.
  • Ogłoszony Rozmiar Okna (rwnd): Najnowsza wartość rozmiaru okna otrzymana od odbiorcy.

Na tej podstawie nadawca oblicza swoje efektywne okno wysyłania, czyli ilość nowych danych, które może wysłać:

Okno Efektywne=rwnd−(LBS−LBA)\text{Okno Efektywne} = \text{rwnd} - (\text{LBS} - \text{LBA})

Jest to ogłoszone okno pomniejszone o ilość danych już będących w drodze (wysłanych, ale jeszcze niepotwierdzonych). Prawa krawędź okna wynika z numeru potwierdzenia i wartości pola okna. Wartość ogranicza się do zera, gdy wynik byłby ujemny. W praktyce nadawcę ogranicza również okno przeciążenia (cwndcwnd), więc ilość nowych danych nie przekracza mniejszej z wartości rwndrwnd i cwndcwnd.

Przykład działania przesuwnego okna

Poniższy prosty scenariusz transferu pliku pokazuje działanie przesuwnego okna.

  1. Stan Początkowy:Połączenie jest w stanie ESTABLISHED. Klient (nadawca) chce wysłać plik o wielkości 10 000 bajtów do serwera (odbiorcy). Serwer ogłasza początkowe okno odbiorcze ('rwnd') o wielkości 4 000 bajtów. Obie strony zsynchronizowały swoje numery sekwencyjne, zaczynając od 1. Klient ma puste okno wysyłania. Może wysłać do 4 000 bajtów.
  2. Nadawca Transmituje Dane: Aplikacja nadawcy dostarcza dane. Nadawca tworzy kilka segmentów. Dla uproszczenia załóżmy, że tworzy dwa segmenty po 1 000 bajtów każdy i wysyła je natychmiast.
    • Segment 1: Zawiera bajty 1-1000.
    • Segment 2: Zawiera bajty 1001-2000.
    Ostatni Wysłany Bajt (LBS) klienta to teraz 2000. Ma on 2 000 bajtów danych w drodze (wysłanych, ale jeszcze niepotwierdzonych). Jego użyteczne okno skurczyło się do 4000−2000=20004000 - 2000 = 2000 bajtów. Może jeszcze wysłać 2000 bajtów, zanim będzie musiał się zatrzymać i czekać na ACK.
  3. Odbiorca Potwierdza Dane: Serwer otrzymuje oba segmenty poprawnie. Jego aplikacja odczytuje pierwsze 1000 bajtów z bufora, zwalniając miejsce. Serwer odsyła segment ACK.
    • Numer Potwierdzenia: 20012001 (potwierdzając odbiór wszystkich bajtów do 2000 i prosząc o następny).
    • Rozmiar Okna: Jego całkowity bufor to 4000 bajtów. Otrzymał bajty 1001-2000, które są w buforze, ale aplikacja odczytała pierwsze 1000. Powiedzmy, że ma teraz 3000 bajtów wolnego miejsca. Ogłasza 'rwnd' = 3000.
  4. Nadawca Przesuwa Okno:Klient otrzymuje ACK. Teraz wie, że bajty 1-2000 zostały pomyślnie dostarczone. Może "przesunąć" swoje okno do przodu.
    • Jego Ostatni Potwierdzony Bajt (LBA) to teraz 2000.
    • Ilość danych w drodze staje się 0 (LBS−LBA=2000−2000=0LBS - LBA = 2000 - 2000 = 0).
    • Aktualizuje również swoje rozumienie okna odbiorcy do nowo ogłoszonej wartości 'rwnd' równej 3000.
    • Jego użyteczne okno wynosi teraz pełne 3 000 bajtów. Może natychmiast wysłać bajty od 2001 do 5000.

Ten proces wysyłania danych, aktualizowania ilości danych w drodze, otrzymywania potwierdzeń i przesuwania okna powtarza się w sposób ciągły. Wartość rwnd\text{rwnd} zmienia limit po stronie odbiorcy, a ACK o wyższym numerze potwierdzenia przesuwa lewą krawędź okna i zwalnia miejsce na kolejne bajty.

Przypadki Specjalne i Problemy w Kontroli Przepływu

Mechanizm przesuwnego okna obsługuje zwykły transfer, lecz występują także przypadki zerowego okna i małych aktualizacji. TCP definiuje dla nich osobne procedury.

Problem Okna Zerowego i Sondy

Co się stanie, jeśli aplikacja odbiorcy przestanie odczytywać dane, a jego bufor odbiorczy całkowicie się zapełni? W takim przypadku odbiorca ogłosi rozmiar okna równy 0. Jest to jasny sygnał dla nadawcy: NATYCHMIAST PRZESTAŃ WYSYŁAĆ NOWE DANE. Nadawca wstrzymuje nowe dane, lecz TCP nadal dopuszcza sondowanie okna zerowego.

Stwarza to potencjalny impas. Nadawca czeka teraz na aktualizację z niezerowym oknem. Odbiorca wyśle taką aktualizację dopiero, gdy jego aplikacja odczyta dane, ale segment zawierający tę aktualizację okna może zaginąć w sieci. Gdyby zaginął, nadawca czekałby wiecznie, a połączenie utknęłoby w martwym punkcie.

Aby temu zapobiec, po otrzymaniu ogłoszenia o oknie zerowym nadawca uruchamia licznik czasu podtrzymania (ang. persist timer). Gdy licznik wygaśnie, nadawca wysyła zwykle jednobajtową Sondę Okna Zerowego (ang. Zero-Window Probe), jeśli ma nowe dane, albo retransmituje wcześniejszy segment. Sonda wymusza odpowiedź z potwierdzeniem zawierającym aktualny rozmiar okna. Przy wartości zero nadawca resetuje licznik i próbuje ponownie później. Przy wartości niezerowej może wznowić transmisję. Mechanizm sondowania ogranicza ryzyko trwałego zablokowania po utracie aktualizacji okna.

Syndrom Małego Okna (SWS)

SWS powoduje transmisję wielu bardzo małych segmentów danych i może wyraźnie obniżyć wydajność TCP. Może wynikać z częstego ogłaszania małego okna przez odbiorcę albo z wysyłania małych porcji przez nadawcę. Ograniczanie aktualizacji i łączenie danych zmniejsza narzut.

  • Odbiorca z małymi aktualizacjami: Jeśli aplikacja odczytuje dane bajt po bajcie, po każdym odczycie zwalnia się jeden bajt bufora. Odbiorca może wtedy ogłosić okno o wielkości 1 bajta. Nadawca wysłałby segment jednobajtowy z 20-bajtowym nagłówkiem TCP i 20-bajtowym nagłówkiem IP. Transmisja 1 bajtu danych w 40-bajtowym segmencie jest nieefektywna.
    Rozwiązanie: Odbiorca powinien poczekać, aż zwolni się znacząca ilość miejsca w buforze (np. połowa bufora lub co najmniej jeden MSS), zanim ogłosi większe okno.
  • Nadawca wysyłający pojedyncze bajty: Aplikacja nadawcy może generować dane bajt po bajcie, na przykład po naciśnięciach klawiszy w zdalnej sesji terminalowej. Wysyłanie każdego bajtu jako osobnego segmentu TCP powoduje narzut 40 bajtów nagłówków na 1 bajt danych.
    Rozwiązanie: . Pozwala on nadawcy na wysłanie pierwszego małego segmentu, ale następnie przechowuje wszelkie kolejne małe fragmenty danych w swoim buforze. Czeka na powrót potwierdzenia dla pierwszego segmentu, zanim spakuje wszystkie zbuforowane małe fragmenty w jeden, większy segment i go wyśle.

Dostosowanie do Nowoczesnych Sieci: Opcja Skalowania Okna

Oryginalny projekt TCP z 16-bitowym polem Rozmiar Okna ograniczał maksymalne okno odbiorcze do 65 535 bajtów (około 64 KiB). Ta wartość wystarczała przy ówczesnych parametrach sieci, lecz w szybkich połączeniach o dużym opóźnieniu ograniczała przepustowość.

Ograniczeniem jest Iloczyn Przepustowości i Opóźnienia (BDP). BDP określa ilość danych, która może znajdować się w tranzycie na ścieżce podczas jednego RTT.

BDP=Przepustowosˊcˊ×Czas Obiegu (RTT)\text{BDP} = \text{Przepustowość} \times \text{Czas Obiegu (RTT)}

BDP określa ilość danych, która może znajdować się w tranzycie podczas jednego RTT. Aby wykorzystać dostępną przepustowość, okno wysyłania powinno być co najmniej tak duże jak BDP.

Dla połączenia z Warszawy do Nowego Jorku o przepustowości 1 Gb/s i RTT 100 ms BDP wynosi około 12,5 MB. Wynika to z działania 1 000 000 000×0,1/81\,000\,000\,000 \times 0{,}1 / 8. Okno 64 KiB jest znacznie mniejsze od tej wartości. Nadawca wysłałby 64 KiB danych, a następnie czekałby na ich przejście przez Atlantyk i powrót potwierdzenia przed wysłaniem kolejnej porcji.

Aby rozwiązać ten problem, wprowadzono opcję Skalowania Okna TCP. Podczas trójetapowego uzgadniania obie strony mogą negocjować współczynnik skali od 0 do 14. Opcja występuje tylko w segmentach SYN, a uzgodnione przesunięcie stosuje się przy interpretacji 16-bitowego pola okna w późniejszych segmentach. Współczynnik określa liczbę bitów, o którą przesuwa się w lewo wartość z 16-bitowego pola Rozmiar Okna. Na przykład współczynnik 8 oznacza pomnożenie wartości przez 282^8 (256). Każda strona negocjuje własny współczynnik, który dotyczy kierunku danych od drugiej strony. Wartość skali nie zmienia szerokości pola w nagłówku, tylko sposób interpretacji jego zawartości. Nadawca nadal uwzględnia także ogłoszone okno odbiorcy i własne okno przeciążenia. Opcja pozwala uzyskać efektywne okno odbiorcze do około 1 GiB, co umożliwia TCP wykorzystanie przepustowości szybkich sieci.

Powiązane artykuły