Menu
Jest wolny
rejestracja
Dom  /  Rada/ Aplikacja serwer klienta tcp ip. Programowanie sieciowe — TCP

Aplikacja serwera klienta Tcp ip. Programowanie sieciowe — TCP

Aplikacja klient-serwer w gnieździe strumieniowym TCP

W poniższym przykładzie używamy protokołu TCP, aby zapewnić uporządkowane, niezawodne dwukierunkowe strumienie bajtów. Zbudujmy kompletną aplikację, która zawiera klienta i serwer. Najpierw pokazujemy, jak zbudować serwer na gniazdach strumieniowych TCP, a następnie aplikację kliencką do testowania naszego serwera.

Poniższy program tworzy serwer, który odbiera żądania połączeń od klientów. Serwer jest zbudowany synchronicznie, dlatego wykonanie wątku jest blokowane do momentu, gdy serwer wyrazi zgodę na połączenie się z klientem. Ta aplikacja przedstawia prosty serwer, który odpowiada klientowi. Klient kończy połączenie wysyłając wiadomość do serwera .

Serwer TCP

Tworzenie struktury serwera przedstawia poniższy schemat funkcjonalny:

Oto kompletny kod programu SocketServer.cs:

// SocketServer.cs przy użyciu systemu; za pomocą System.Text; za pomocą System.Net; za pomocą System.Net.Sockets; Przestrzeń nazw SocketServer (klasa Program (statyczny void Main (argi ciągu) (// Ustaw lokalny punkt końcowy gniazda IPHostEntry ipHost = Dns.GetHostEntry ("localhost"); IPAddress ipAddr = ipHost.AddressList; IPEndPoint ipEndPoint = new IPEndPoint (ipAddr, 11 ); // Utwórz gniazdo Tcp / Ip sListener = new Socket (ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // Przypisz gniazdo do lokalnego punktu końcowego i nasłuchuj prób przychodzących gniazd (sListener.Bind (ipEndPoint) sListener. Listen (10); // Rozpocznij nasłuchiwanie połączeń podczas (true) (Console.WriteLine ("Oczekiwanie na połączenie na porcie (0)", ipEndPoint); // Program zatrzymuje się, czekając na połączenie przychodzące Socket handler = sListener.Accept (); string data = null; // Czekaliśmy na klienta próbującego się z nami połączyć byte bytes = new byte; int bytesRec = handler.Receive (bytes); data + = Encoding.UTF8.GetString (bytes, 0, bytesRec); // Pokaż dane na konsoli Console.Write ("Otrzymano tekst: "+ dane +" \ n \ n "); // Wyślij odpowiedź do klienta \ string response = "Dziękujemy za żądanie w" + data.Length.ToString () + "znaki"; byte msg = Encoding.UTF8.GetBytes (odpowiedź); handler.Wyślij (wiadomość); if (data.IndexOf (" ")> -1) (Console.WriteLine (" Serwer zakończył łączenie się z klientem. "); Break;) handler.Shutdown (SocketShutdown.Both); handler.Close ();)) catch (wyjątek ex) ( Console.WriteLine (ex.ToString ());) wreszcie (Console.ReadLine ();))))

Przyjrzyjmy się strukturze tego programu.

Pierwszym krokiem jest ustanowienie lokalnego punktu końcowego gniazda. Przed otwarciem gniazda w celu nasłuchiwania połączeń należy przygotować dla niego adres lokalnego punktu końcowego. Unikalny adres dla usługi TCP/IP jest określany przez kombinację adresu IP hosta z numerem portu usługi, który tworzy punkt końcowy usługi.

Klasa Dns udostępnia metody, które zwracają informacje o adresach sieciowych obsługiwanych przez urządzenie w sieci lokalnej. Jeśli urządzenie LAN ma więcej niż jeden adres sieciowy, klasa Dns zwraca informacje o wszystkich adresach sieciowych, a aplikacja musi wybrać odpowiedni adres z tablicy do obsługi.

Utwórz IPEndPoint dla serwera, łącząc pierwszy adres IP hosta z metody Dns.Resolve() z numerem portu:

IPHostEntry ipHost = Dns.GetHostEntry ("localhost"); AdresIP ipAddr = ipHost.ListaAdresów; IPEndPoint ipEndPoint = nowy IPEndPoint (ipAddr, 11000);

Tutaj klasa IPEndPoint reprezentuje host lokalny na porcie 11000. Następnie utwórz gniazdo strumienia z nową instancją klasy Socket. Gdy lokalny punkt końcowy jest skonfigurowany do nasłuchiwania połączeń, można utworzyć gniazdo:

Socket sListener = new Socket (ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

Wyliczenie AdresRodzina określa schematy adresowania, których wystąpienie klasy Socket może użyć do rozwiązania adresu.

W parametrze Rodzaj gniazda istnieją gniazda TCP i UDP. W nim możesz zdefiniować m.in. następujące wartości:

Dgram

Obsługuje datagramy. Wartość Dgram wymaga określenia Udp dla typu protokołu i InterNetwork w parametrze rodziny adresów.

Surowe

Obsługuje dostęp do podstawowego protokołu transportowego.

Strumień

Obsługuje gniazda strumieniowe. Wartość Stream wymaga określenia Tcp dla typu protokołu.

Trzeci i ostatni parametr określa typ protokołu wymaganego dla gniazda. W parametrze Typ protokołu możesz określić następujące najważniejsze wartości - Tcp, Udp, Ip, Raw.

Następnym krokiem powinno być przypisanie gniazda za pomocą metody Wiąże ()... Gdy gniazdo jest otwierane przez konstruktor, nie jest mu przypisywana żadna nazwa, zarezerwowany jest tylko deskryptor. Metoda Bind() jest wywoływana w celu przypisania nazwy do gniazda serwera. Aby gniazdo klienta było w stanie zidentyfikować gniazdo strumieniowe TCP, program serwera musi nazwać jego gniazdo:

SListener.Bind (ipEndPoint);

Metoda Bind () wiąże gniazdo z lokalnym punktem końcowym. Musisz wywołać metodę Bind () przed próbami wywołania metod Listen () i Accept ().

Teraz, po utworzeniu gniazda i skojarzeniu z nim nazwy, możesz odsłuchiwać przychodzące wiadomości za pomocą metody Słuchać ()... W stanie nasłuchu gniazdo będzie czekać na przychodzące próby połączenia:

SListener.Słuchaj (10);

Parametr określa zaległości który określa maksymalną liczbę oczekujących połączeń w kolejce. W podanym kodzie wartość parametru pozwala na zgromadzenie w kolejce do dziesięciu połączeń.

W stanie nasłuchu należy być gotowym na wyrażenie zgody na połączenie z klientem, do którego metoda jest wykorzystywana Zaakceptować ()... Ta metoda uzyskuje połączenie klienta i wykonuje powiązania nazwy klient/serwer. Metoda Accept () blokuje wątek wywołującego do momentu nadejścia połączenia.

Metoda Accept () pobiera pierwsze żądanie połączenia z oczekującej kolejki żądań i tworzy nowe gniazdo do jego obsługi. Chociaż nowe gniazdo jest tworzone, oryginalne gniazdo nadal nasłuchuje i może być wielowątkowe w celu odbierania wielu żądań połączeń od klientów. Żadna aplikacja serwera nie powinna zamykać gniazda nasłuchującego. Powinien nadal działać wraz z gniazdami utworzonymi przez metodę Accept do obsługi przychodzących żądań klientów.

While (true) (Console.WriteLine ("Oczekiwanie na połączenie na porcie (0)", ipEndPoint); // Program zatrzymuje się, czekając na połączenie przychodzące Socket handler = sListener.Accept ();

Gdy klient i serwer nawiążą między sobą połączenie, możesz wysyłać i odbierać wiadomości za pomocą metod Wysłać () oraz Odbierać () Klasa gniazda.

Metoda Send() zapisuje dane wychodzące do gniazda, z którym nawiązywane jest połączenie. Metoda Receive() odczytuje dane przychodzące do gniazda strumienia. W systemie opartym na protokole TCP przed wykonaniem metod Send() i Receive() należy nawiązać połączenie między gniazdami. Dokładny protokół między dwoma oddziałującymi jednostkami musi zostać określony z wyprzedzeniem, aby aplikacje klienckie i serwerowe nie blokowały się nawzajem, nie wiedząc, kto powinien wysłać ich dane jako pierwszy.

Po zakończeniu wymiany danych między serwerem a klientem należy zakończyć połączenie za pomocą metod Zamknąć () oraz Blisko ():

Handler.Shutdown (SocketShutdown.Both); handler.Zamknij ();

SocketShutdown to wyliczenie zawierające trzy wartości do zatrzymania: Obie- przestaje wysyłać i odbierać dane przez gniazdo, Odbierać- przestaje odbierać dane w gnieździe i Wysłać- przestaje wysyłać dane przez gniazdo.

Gniazdo jest zamykane po wywołaniu metody Close (), która również ustawia właściwość Connected gniazda na wartość false.

Klient na TCP

Funkcje używane do tworzenia aplikacji klienckiej mniej więcej przypominają aplikację serwerową. Podobnie jak w przypadku serwera, te same metody są używane do określania punktu końcowego, tworzenia instancji gniazda, wysyłania i odbierania danych oraz zamykania gniazda.

TCP w naturalny sposób integruje się ze środowiskiem klient/serwer (patrz Rysunek 10.1). Aplikacja serwerowa słucha(nasłuchiwanie) przychodzących żądań połączeń. Na przykład usługi WWW, File Transfer lub Terminal Access nasłuchują żądań klientów. Komunikacja w TCP jest inicjowana przez odpowiednie podprogramy, które inicjują połączenie z serwerem (patrz rozdział 21 o interfejsie programowania gniazd).

Ryż. 10.1. Klient wywołuje serwer.

W rzeczywistości klientem może być inny serwer. Na przykład serwery pocztowe mogą łączyć się z innymi serwery pocztowe do przekazywania wiadomości E-mail między komputerami.

10.2 Koncepcje TCP

W jakiej formie aplikacje powinny przesyłać dane przez TCP? Jak TCP przesyła dane do IP? W jaki sposób wysyłający i odbierający protokoły TCP identyfikują połączenie między aplikacjami i elementami danych wymaganymi do jego implementacji? Odpowiedzi na wszystkie te pytania znajdują się w poniższych sekcjach, które opisują podstawowe koncepcje TCP.

10.2.1 Strumienie danych wejściowych i wyjściowych

Konceptualistyczny model połączenia zakłada, że ​​aplikacja wysyła strumień danych do aplikacji równorzędnej. Jednocześnie może odbierać strumień danych od swojego partnera połączenia. TCP zapewnia pełny dupleks(pełny dupleks) tryb pracy, w którym jednocześnie dwa strumienie dane (patrz Rysunek 10.2).


Ryż. 10.2. Aplikacje wymieniają strumienie danych.

10.2.2 Segmenty

TCP może przekształcić strumień danych opuszczający aplikację w formę odpowiednią do umieszczenia w datagramach. Jak?

Aplikacja przesyła dane w TCP, a ten protokół umieszcza je w bufor wyjściowy(wyślij bufor). Następnie TCP wycina porcje danych z bufora i wysyła je, dodając nagłówek (w tym przypadku segmenty- człon). Na ryc. 10.3 pokazuje, jak dane z bufor wyjściowy Protokół TCP jest pakowany w segmenty. TCP przesyła segment do IP w celu dostarczenia jako oddzielny datagram. Pakowanie danych w porcje o odpowiedniej długości zapewnia, że ​​dane są przesyłane wydajnie, więc przed utworzeniem segmentu TCP poczeka, aż odpowiednia ilość danych pojawi się w buforze wyjściowym.


Ryż. 10.3 Tworzenie segmentu TCP

10.2.3 Wyrzucanie

Jednak dużych ilości danych często nie można zastosować w rzeczywistych aplikacjach. Na przykład, gdy program kliencki użytkownika końcowego inicjuje sesję interaktywną ze zdalnym serwerem, użytkownik wprowadza tylko polecenia (po czym następuje naciśnięcie klawisza Powrót).

Program kliencki użytkownika potrzebuje, aby TCP wiedział o wysyłaniu danych do zdalnego hosta i mógł to zrobić natychmiast. W takim przypadku użyj wyrzucanie(naciskać).

Jeśli spojrzysz na operacje w sesji interaktywnej, możesz znaleźć wiele segmentów z niewielką ilością danych, a co więcej, nierówności można znaleźć w prawie każdym segmencie danych. Jednak wypychanie nie powinno być stosowane podczas przesyłania plików (z wyjątkiem ostatniego segmentu), a protokół TCP będzie w stanie najefektywniej pakować dane w segmenty.

10.2.4 Pilne dane

Model przekazywania aplikacji zakłada zastosowanie uporządkowanego strumienia bajtów, który dociera do miejsca docelowego. Odwołując się ponownie do przykładu sesji interaktywnej, załóżmy, że użytkownik nacisnął klawisz Uwaga(uwaga) lub przerwa(przerywać). Zdalna aplikacja musi być w stanie pominąć zakłócające bajty i jak najszybciej reagować na naciśnięcie klawisza.

Mechanizm pilne dane(dane pilne) oznacza specjalne informacje w segmencie jako pilne. W ten sposób TCP informuje swojego partnera, że ​​segment zawiera pilne dane i może wskazać, gdzie się znajduje. Partner powinien jak najszybciej przekazać te informacje do aplikacji docelowej.

10.2.5 Porty aplikacji

Klient musi zidentyfikować usługę, do której chce uzyskać dostęp. Odbywa się to poprzez określenie adresu IP usługi hosta i jego numeru portu TCP. Podobnie jak w przypadku UDP, numery portów TCP mieszczą się w zakresie od 0 do 65535. Porty w zakresie od 0 do 1023 są określane jako dobrze znane i służą do uzyskiwania dostępu do standardowych usług.

Kilka przykładów dobrze znanych portów i odpowiadających im zastosowań przedstawiono w tabeli 10.1. Usługi Odrzucać(port 9) i ładować(port 19) to wersje TCP usług, które znamy już z UDP. Pamiętaj, że ruch TCP na porcie 9 jest całkowicie odizolowany od ruchu UDP na porcie 9.


Tabela 10.1 Powszechnie znane porty TCP i odpowiadające im aplikacje

Port Podanie Opis
9 Odrzucać Anulowanie wszystkich przychodzących danych
19 Naładowany Generator symboli. Wymiana strumienia znaków
20 Dane FTP Port przesyłania danych FTP
21 FTP Port do konwersacji FTP
23 TELNET Port do zdalnej rejestracji Telnet
25 SMTP port SMTP
110 POP3 Pobieranie usługi pocztowej na komputery osobiste
119 NNTP Dostęp do aktualności online

A co z portami używanymi przez klientów? W rzadkich przypadkach klient nie działa przez dobrze znany port. Ale w takich sytuacjach, chcąc otworzyć połączenie, często prosi system operacyjny o przypisanie mu nieużywanego i niezarezerwowanego portu. Po zakończeniu połączenia klient jest zobowiązany do zwrotu tego portu, po czym port może być ponownie wykorzystany przez innego klienta. Ponieważ w niezarezerwowanej puli numerów jest ponad 63 000 portów TCP, limity portów klienta można zignorować.

10.2.6 adresy gniazd

Jak już wiemy, połączenie adresu IP i portu do komunikacji nazywa się gniazdo elektryczne. Połączenie TCP jest w pełni identyfikowane przez adres gniazda na każdym końcu tego połączenia. Na ryc. 10.4 przedstawia połączenie między klientem w gnieździe (128.36.1.24, port = 3358) a serwerem w gnieździe (130.42.88.22, port = 21).

Ryż. 10.4. Adresy gniazd

Każdy nagłówek datagramu zawiera źródłowy i docelowy adres IP. Zobaczymy później, że numery portów źródłowych i docelowych są wskazane w nagłówku segmentu TCP.

Zazwyczaj serwer jest w stanie zarządzać wieloma klientami jednocześnie. Unikalne adresy gniazd serwera są przypisywane jednocześnie wszystkim jego klientom (patrz Rysunek 10.5).


Ryż. 10.5. Wielu klientów podłączonych do adresów gniazda serwera

Ponieważ datagram zawiera segment połączenia TCP identyfikowany przez adresy IP i porty, serwerowi bardzo łatwo jest śledzić połączenia wielu klientów.

10.3 Mechanizm niezawodności TCP

W tej sekcji przyjrzymy się mechanizmowi TCP używanemu do niezawodnego dostarczania danych przy zachowaniu kolejności przekazywania i unikaniu utraty lub duplikacji.

10.3.1 Numeracja i potwierdzenie

Protokół TCP wykorzystuje numerację i potwierdzenia (ACK), aby zapewnić niezawodny transfer danych. Schemat numeracji TCP jest nieco nietypowy: każdy przekierowanie połączenia oktet jest uważany za posiadający kolejny numer. Nagłówek segmentu TCP zawiera numer sekwencyjny pierwszy oktet danych tego segmentu.

Odbiorca jest zobowiązany do potwierdzenia otrzymania danych. Jeśli żadne potwierdzenie nie nadejdzie w określonym przedziale czasu, dane są przesyłane ponownie. Ta metoda nazywa się pozytywne potwierdzenie z przekaźnikiem(pozytywne potwierdzenie z retransmisją).

Odbiornik TCP ściśle monitoruje przychodzące numery sekwencyjne, aby upewnić się, że dane są odbierane w spójny sposób i że nie ma brakujących części. Ponieważ potwierdzenia ACK mogą zostać losowo utracone lub opóźnione, do odbiorcy mogą dotrzeć zduplikowane segmenty. Numery sekwencyjne pozwalają zidentyfikować zduplikowane dane, które są następnie odrzucane.

Na ryc. 10.6 przedstawia uproszczony wygląd limitu czasu TCP i retransmisji.


Ryż. 10.6. Limit czasu i retransmisja w TCP

10.3.2 Pola portu, sekwencji i ACK w nagłówku TCP

Jak pokazano na ryc. 10.7, kilka pierwszych pól nagłówka TCP zapewnia miejsce na port źródłowy i docelowy, numer sekwencyjny pierwszego bajtu osadzonych danych oraz potwierdzenie ACK równe numerowi sekwencyjnemu Następny oczekiwany bajt na drugim końcu. Innymi słowy, jeśli TCP odbiera wszystkie bajty do 30. od swojego partnera, to pole będzie miało wartość 31, wskazując segment do przekazania.


Ryż. 10.7. Wartości początkowe w polach nagłówka TCP

Należy zwrócić uwagę na jeden mały szczegół. Załóżmy, że TCP wysłał bajty od 1 do 50 lub więcej, nie ma danych do wysłania. W przypadku odebrania danych od partnera, TCP ma obowiązek potwierdzić ich odbiór, za co wyśle ​​nagłówek bez żadnych danych z nim związanych. Oczywiście ten nagłówek zawiera wartość ACK. Pole sekwencji zawiera wartość 51, czyli numer następnego bajtu, który zamierza wyślij TCP. Gdy TCP wyśle ​​następne dane, nowy nagłówek TCP również będzie miał wartość 51 w polu sekwencji.

10.4 Nawiązywanie połączenia

Jak te dwie aplikacje łączą się ze sobą? Każdy z nich przed komunikacją wywołuje podprogram tworzący blok pamięci, który posłuży do przechowywania parametrów TCP i IP tego połączenia, np. adresy gniazd, bieżący numer sekwencyjny, początkowa wartość czasu życia itp.

Aplikacja serwera czeka na pojawienie się klienta, który chcąc uzyskać dostęp do serwera wysyła żądanie o pogarszać(połączenia) identyfikujące adres IP i port serwera.

Jest jedna osobliwość techniczna. Każda strona rozpoczyna numerację każdego bajtu nie jedynką, ale losowy numer sekwencyjny(poniżej dowiemy się, dlaczego tak się dzieje). Oryginalna specyfikacja radzi: wygeneruj początkowy numer sekwencyjny w oparciu o 32-bitowy zewnętrzny zegar, który zwiększa się w przybliżeniu co 4 μs.

10.4.1 Skrypt połączenia

Procedura połączenia jest często określana jako uzgadnianie trójstronne, ponieważ w celu ustanowienia połączenia wymieniane są trzy komunikaty — SYN, SYN i ACK.

Podczas nawiązywania połączenia partnerzy wymieniają trzy ważne informacje:

1. Ilość miejsca w buforze do odbioru danych

2. Maksymalna ilość danych przenoszonych w segmencie przychodzącym

3. Początkowy numer sekwencyjny używany do danych wychodzących

Zauważ, że każda strona stosuje operacje 1 i 2, aby wskazać granice, w których druga strona będzie działać. Komputer osobisty może mieć mały bufor odbiorczy, a superkomputer może mieć duży bufor. Struktura pamięci komputer osobisty może ograniczyć przychodzące porcje danych do 1 KB, a superkomputer jest sterowany za pomocą dużych segmentów.

Możliwość kontrolowania sposobu, w jaki druga strona wysyła dane, jest ważną właściwością skalowalności protokołu TCP/IP.

Na ryc. 10.8 pokazuje przykład skryptu połączenia. Przedstawiono bardzo proste początkowe numery sekwencyjne, aby nie przytłaczać rysunku. Zauważ, że na tym rysunku klient może odbierać większe segmenty niż serwer.


Ryż. 10.8. Nawiązywanie połączenia

Wykonywane są następujące operacje:

1. Serwer jest inicjowany i jest gotowy do połączenia z klientami (ten stan nazywa się pasywnym otwartym).

2. Klient prosi TCP o nawiązanie połączenia z serwerem na podanym adresie IP i porcie (ten stan nazywa się aktywnym otwartym).

3. Klient TCP otrzymuje początkowy numer sekwencyjny (w tym przykładzie - 1000) i wysyła segment synchronizacji(synchronizacja segmentu - SYN). Ten segment zawiera numer sekwencyjny, rozmiar okna odbioru (4K) i największy segment, jaki klient może zaakceptować (1460 bajtów).

4. Po nadejściu SYN serwer TCP odbiera mój początkowy numer porządkowy (3000). Wysyła segment SYN zawierający początkowy numer sekwencji (3000), ACK 1001 (co oznacza, że ​​pierwszy bajt wysłany przez klienta ma numer 1001), rozmiar okna odbioru (4K) i największy segment, jaki serwer może odebrać (1024 bajty). ).

5. Klient TCP po odebraniu wiadomości SYN/ACK z serwera odsyła ACK 3001 (pierwszy bajt danych przesyłanych przez serwer powinien mieć numer 3001).

6. Klient TCP instruuje swoją aplikację, aby otworzyła połączenie.

7. TCP serwera po otrzymaniu komunikatu ACK od TCP klienta informuje swoją aplikację o otwarciu połączenia.

Klient i serwer ogłaszają swoje reguły dla odbieranych danych, synchronizują swoje numery sekwencyjne i przygotowują się do wymiany danych. Specyfikacja TCP dopuszcza również inny (niezbyt udany) scenariusz, w którym aplikacje równorzędne jednocześnie aktywnie otwierają się nawzajem.

10.4.2 Ustawianie wartości parametrów IP

Żądanie połączenia aplikacji może również określać parametry dla datagramów IP, które będą przenosić dane dla tego połączenia. Jeśli nie określono konkretnej wartości parametru, używana jest wartość domyślna.

Na przykład aplikacja może wybrać żądaną wartość priorytetu IP lub typu usługi. Ponieważ każda z podłączonych stron samodzielnie ustala własny priorytet i rodzaj usługi, teoretycznie wartości te mogą się różnić dla różnych kierunków przepływu danych. Z reguły w praktyce dla każdego kierunku wymiany stosuje się te same wartości.

Gdy aplikacja korzysta z opcji zabezpieczeń dla agencji rządowych lub wojskowych, każdy punkt końcowy połączenia musi używać tych samych poziomów zabezpieczeń, w przeciwnym razie połączenie nie zostanie nawiązane.

10.5 Transfer danych

Transmisja danych rozpoczyna się po zakończeniu trzyetapowego potwierdzenia nawiązania połączenia (patrz rys. 10.9). Standard TCP umożliwia uwzględnienie normalnych danych w segmentach potwierdzeń, ale nie zostaną one dostarczone do aplikacji, dopóki połączenie nie zostanie nawiązane. Dla ułatwienia numerowania używane są wiadomości 1000-bajtowe. Każdy segment nagłówka TCP ma pole ACK, które identyfikuje numer sekwencyjny bajtu, który ma zostać odebrany od peera w połączeniu..


Ryż. 10.9. Prosty przepływ danych i ACK

Pierwszy segment wysyłany przez klienta zawiera bajty od 1001 do 2000. Jego pole ACK powinno zawierać wartość 3001, co wskazuje na kolejny numer bajtu, który ma zostać odebrany z serwera.

Serwer odpowiada klientowi segmentem zawierającym 1000 bajtów danych (począwszy od 3001). Jego pole ACK nagłówka TCP wskaże, że bajty od 1001 do 2000 zostały już pomyślnie odebrane, więc następny oczekiwany numer sekwencyjny segmentu powinien wynosić 2001.

Klient następnie wysyła segmenty zaczynając od bajtów 2001, 3001 i 4001 w tej kolejności. Należy zauważyć, że klient nie oczekuje potwierdzenia ACK po każdym z wysłanych segmentów. Dane są wysyłane do partnera do momentu zapełnienia jego przestrzeni buforowej (poniżej zobaczymy, że odbiorca może bardzo dokładnie wskazać ilość przesłanych do niego danych).

Serwer oszczędza przepustowość, używając pojedynczego potwierdzenia potwierdzającego pomyślne przekazanie wszystkich segmentów.

Na ryc. 10.10 pokazuje transfer danych po utracie pierwszego segmentu. Po upływie limitu czasu segment jest przesyłany ponownie. Należy zauważyć, że po odebraniu utraconego segmentu odbiorca wysyła jedno potwierdzenie potwierdzające, że oba segmenty zostały wysłane.


Ryż. 10.10. Utrata danych i retransmisja

10.6 Zamykanie połączenia

Normalne zakończenie połączenia odbywa się przy użyciu tej samej procedury potrójnego uzgadniania, jak podczas otwierania połączenia. Każda ze stron może rozpocząć zamykanie połączenia w następującym scenariuszu:

A:

B:"Dobry".

V:– Ja też skończyłem pracę.

A:"Dobry".

Dopuszczalny jest również następujący scenariusz (choć jest używany niezwykle rzadko):

A:„Skończyłem. Nie ma więcej danych do wysłania”.

V:„Dobrze. Jednak są pewne dane…”

V:– Ja też skończyłem pracę.

A:"Dobry".

W poniższym przykładzie połączenie zamyka serwer, jak to często ma miejsce w przypadku komunikacji klient/serwer. W takim przypadku po wejściu użytkownika w sesję telnet polecenia wylogowania serwer inicjuje żądanie zamknięcia połączenia. W sytuacji pokazanej na ryc. 10.11 wykonywane są następujące czynności:

1. Aplikacja na serwerze każe TCP zamknąć połączenie.

2. Serwer TCP wysyła segment końcowy (FIN), informując swojego partnera, że ​​nie ma więcej danych do wysłania.

3. TCP klienta wysyła potwierdzenie ACK do segmentu FIN.

4. TCP klienta informuje jego aplikację, że serwer chce zamknąć połączenie.

5. Aplikacja kliencka informuje swój protokół TCP o zamknięciu połączenia.

6. TCP klienta wysyła komunikat FIN.

7. Serwer TCP odbiera FIN od klienta i odpowiada komunikatem ACK.

8. Serwer TCP nakazuje swojej aplikacji zamknięcie połączenia.


Ryż. 10.11. Zamykanie połączenia

Obie strony mogą rozpocząć zamykanie w tym samym czasie. W takim przypadku normalne zamknięcie połączenia jest zakończone po wysłaniu przez każdego partnera komunikatu ACK.

10.6.1 Nagłe zakończenie

Każda ze stron może zażądać nagłego zamknięcia połączenia. Jest to akceptowalne, gdy aplikacja chce zakończyć połączenie lub gdy TCP napotka poważny problem z komunikacją, którego nie może rozwiązać samodzielnie. Nagłe zakończenie jest żądane przez wysłanie jednego lub więcej komunikatów resetowania do peera, zgodnie z określoną flagą w nagłówku TCP.

10.7 Kontrola przepływu

Odbiornik TCP jest ładowany przychodzącym strumieniem danych i określa, ile informacji może odebrać. To ograniczenie dotyczy nadawcy TCP. Poniższe wyjaśnienie tego mechanizmu jest koncepcyjne, a programiści mogą go zaimplementować w swoich produktach na różne sposoby.

Podczas konfiguracji połączenia każdy partner przydziela miejsce na bufor wejściowy połączenia i powiadamia o tym drugą stronę. Zazwyczaj rozmiar bufora jest wyrażany jako liczba całkowita maksymalnych rozmiarów segmentu.

Strumień danych wchodzi do bufora wejściowego i jest tam przechowywany przed wysłaniem do aplikacji (określany przez port TCP). Na ryc. 10.12 pokazuje bufor wejściowy zdolny do przyjęcia 4 KB.


Ryż. 10.12. Okno odbioru bufora wejściowego

Przestrzeń bufora zapełnia się w miarę napływania danych. Gdy aplikacja odbierająca pobiera dane z bufora, zwolnione miejsce staje się dostępne dla nowych danych przychodzących.

10.7.1 Okno odbioru

Okno odbioru(okno odbioru) - dowolna przestrzeń w buforze wejściowym nie zajęta jeszcze przez dane. Dane pozostają w buforze wejściowym, dopóki nie zostaną wykorzystane przez aplikację docelową. Dlaczego aplikacja nie pobiera danych od razu?

Prosty scenariusz pomoże odpowiedzieć na to pytanie. Załóżmy, że klient przesłał plik na serwer FTP działający na bardzo obciążonym komputerze z wieloma użytkownikami. Program FTP musi wtedy odczytać dane z bufora i zapisać je na dysku. Gdy serwer wykonuje operacje we/wy dysku, program czeka na zakończenie tych operacji. W tym momencie może zostać uruchomiony inny program (na przykład zgodnie z harmonogramem), a gdy program FTP zostanie uruchomiony ponownie, w buforze pojawią się już następujące dane.

Okno odbioru rozszerza się od ostatniego potwierdzonego bajtu do końca bufora. Na ryc. 10.12 najpierw dostępny jest cały bufor, a zatem dostępne jest okno odbioru 4 KB. Gdy nadejdzie pierwszy KB, okno odbiorcze zmniejszy się do 3 KB (dla uproszczenia przyjmiemy, że każdy segment to 1 KB, chociaż w praktyce wartość ta różni się w zależności od potrzeb aplikacji). Pojawienie się kolejnych dwóch segmentów o rozmiarze 1 KB zmniejszy okno odbioru do 1 KB.

Każde ACK wysłane przez odbiornik zawiera informację o aktualnym stanie okna odbiorczego, w zależności od tego, który przepływ danych ze źródła jest regulowany.

W większości przypadków rozmiar bufora wejściowego jest ustawiany podczas uruchamiania połączenia, chociaż standard TCP nie określa sposobu obsługi tego bufora. Bufor wejściowy może się powiększać lub zmniejszać, aby przekazać informację zwrotną do nadawcy.

Co się stanie, jeśli przychodzący segment można umieścić w oknie odbioru, ale nie dotarł on w kolejności? Ogólnie przyjmuje się, że wszystkie implementacje przechowują przychodzące dane w oknie odbioru i wysyłają potwierdzenie (ACK) tylko dla całego ciągłego bloku kilku segmentów. Jest to poprawna metoda, ponieważ w przeciwnym razie odrzucenie niesprawnych danych znacznie obniży wydajność.

10.7.2 Okno przesyłania

System przesyłający dane musi śledzić dwie cechy: ile danych zostało już wysłanych i potwierdzonych oraz aktualny rozmiar okna odbiorczego odbiorcy. Aktywny przestrzeń wysyłkowa(spacja wysyłania) rozwija się od pierwszego niezatwierdzonego oktetu na lewo od bieżącego okna odbiorczego. Część okno używany przez wysyłać, wskazuje, o ile więcej dodatkowych danych można przesłać do partnera.

Początkowy numer porządkowy i początkowy rozmiar okna odbierania są ustawiane podczas konfiguracji połączenia. Ryż. 10.13 ilustruje niektóre cechy mechanizmu przesyłania danych.

1. Nadawca zaczyna się od okna wysyłania 4KB.

2. Nadawca przesyła 1 KB. Kopia tych danych jest przechowywana do momentu otrzymania potwierdzenia (ACK), ponieważ może być konieczne ich ponowne przesłanie.

3. Nadchodzi komunikat ACK dla pierwszego KB i wysyłane są następne 2 KB danych. Wynik pokazano w trzeciej części od góry ryc. 10.13. Trwa przechowywanie 2 KB.

4. Na koniec nadchodzi ACK dla wszystkich przesłanych danych (tj. wszystkich odebranych przez odbiorcę). ACK przywraca rozmiar okna wysyłania do 4K.

Ryż. 10.13. Wyślij okno

Należy zwrócić uwagę na kilka interesujących funkcji:

S Nadawca nie czeka na potwierdzenie ACK dla każdego wysłanego segmentu danych. Jedynym ograniczeniem transferu jest rozmiar okna odbioru (na przykład nadawca powinien wysyłać tylko 4K jednobajtowych segmentów).

S Załóżmy, że nadawca wysyła dane w kilku bardzo krótkich segmentach (na przykład 80 bajtów). W takim przypadku dane można ponownie sformatować w celu uzyskania bardziej wydajnej transmisji (na przykład w pojedynczym segmencie).

10.8 Nagłówek TCP

Na ryc. 10.14 pokazuje format segmentu (nagłówek i dane TCP). Nagłówek zaczyna się od identyfikatorów portu źródłowego i docelowego. Następne następne pole numer seryjny(numer kolejny) wskazuje pozycję w wychodzącym strumieniu danych, którą zajmuje ten segment. Pole POTWIERDZ(potwierdzenie) zawiera informacje o oczekiwanym następnym segmencie, który pojawi się w strumieniu danych wejściowych.


Ryż. 10.14. Segment TCP

Jest sześć flag:

Pole stronniczość danych(Przesunięcie danych) zawiera rozmiar nagłówka TCP w słowach 32-bitowych. Nagłówek TCP musi kończyć się na granicy 32-bitowej.

10.8.1 Opcja maksymalnego rozmiaru segmentu

Parametr "maksymalny rozmiar segmentu"(maksymalny rozmiar segmentu - MSS) służy do anonsowania największego fragmentu danych, który może zostać odebrany i przetworzony przez system. Tytuł jest jednak nieco nieprecyzyjny. Zwykle w TCP człon traktowane jako nagłówek plus dane. ale maksymalny rozmiar segmentu zdefiniowana jako:

Największy datagram, jaki możesz zaakceptować, to 40

Innymi słowy, MSS odzwierciedla największe ładunek w odbiorniku o długości nagłówków TCP i IP 20 bajtów. Jeśli w ogóle Dodatkowe opcje, ich długość należy odjąć od całkowitego rozmiaru. W związku z tym ilość danych, które można przesłać w segmencie, określa się jako:

Zadeklarowana wartość MSS + 40 - (suma długości nagłówków TCP i IP)

Peery zazwyczaj wymieniają wartości MSS w początkowych wiadomościach SYN, gdy połączenie jest otwarte. Jeśli system nie ogłasza maksymalnego rozmiaru segmentu, używana jest domyślna wartość 536 bajtów.

Rozmiar maksymalnego segmentu jest zakodowany z 2-bajtową preambułą, po której następuje 2-bajtowa wartość, tj. największa wartość to 2 16 -1 (65 535 bajtów).

MSS nakłada sztywny limit danych wysyłanych do TCP: odbiorca nie będzie w stanie przetwarzać dużych wartości. Jednak nadawca używa segmentów mniejszy, ponieważ MTU wzdłuż ścieżki jest również określane dla połączenia.

10.8.2 Używanie pól nagłówka w żądaniu połączenia

Pierwszy segment wysłany w celu otwarcia połączenia ma flagę SYN równą 1 i flagę ACK równą 0. Początkowy segment SYN to jedyny segment, który ma pole ACK równe 0. Należy zauważyć, że zabezpieczenia wykorzystują tę funkcję do wykrywania przychodzących żądań sesji TCP.

Pole numer seryjny zawiera początkowy numer sekwencyjny(początkowy numer kolejny), pole okno - początkowy rozmiar okno odbioru. Jedynym aktualnie zdefiniowanym parametrem TCP jest maksymalny rozmiar segmentu (jeśli nie jest określony, domyślnie 536 bajtów), którego oczekuje TCP. Ta wartość ma długość 32 bitów i jest zwykle obecna w żądaniu połączenia w polu opcje(Opcja). Nagłówek TCP zawierający wartość MSS ma długość 24 bajtów.

10.8.3 Korzystanie z pól nagłówka w odpowiedzi połączenia

W odpowiedzi enable na żądanie połączenia obie flagi (SYN i ACK) są równe 1. System odpowiadający wskazuje początkowy numer sekwencyjny w odpowiednim polu i rozmiar okna odbioru w polu Okno. Największy rozmiar segment, którego chce użyć odbiorca, zwykle znajduje się w odpowiedzi na żądanie połączenia (w opcje). Wartość ta może różnić się od wartości strony żądającej połączenia, tj. można zastosować dwie różne wartości.

Żądanie połączenia można odrzucić, określając flagę resetowania (RST) o wartości 1 w odpowiedzi.

10.8.4 Wybór początkowego numeru sekwencji

Specyfikacja TCP zakłada, że ​​podczas nawiązywania połączenia każda ze stron wybiera: początkowy numer sekwencyjny(przy aktualnej wartości 32-bitowego zegara wewnętrznego). Jak to się robi?

Wyobraź sobie, co się dzieje, gdy system się zawiesza. Załóżmy, że użytkownik otworzył połączenie tuż przed awarią i wysłał niewielką ilość danych. Po odzyskaniu system nie pamięta już niczego, co zostało wykonane przed awarią, w tym już uruchomionych połączeń i przypisanych numerów portów. Użytkownik ponownie nawiązuje połączenie. Numery portów nie zgadzają się z pierwotnymi przypisaniami, a niektóre z nich mogą być już używane przez inne połączenia nawiązane kilka sekund przed awarią.

Dlatego druga strona na samym końcu połączenia może nie wiedzieć, że jej partner przeżył załamanie, a jego dzieło zostało wówczas przywrócone. Wszystko to prowadzi do poważnych zakłóceń, zwłaszcza gdy stare dane muszą długo przenosić się w sieci i mieszać z danymi z nowo utworzonego połączenia. Dobór timera do ponownego startu eliminuje takie problemy. Stare dane będą miały inną numerację niż zakres numerów sekwencyjnych nowego połączenia. Hakerzy, fałszując źródłowy adres IP zaufanego hosta, próbują uzyskać dostęp do komputerów, podając w wiadomości przewidywalny numer sekwencji początkowej. Służy do tego funkcja haszowania kryptograficznego oparta na kluczach wewnętrznych Najlepszym sposobem aby wybrać bezpieczne numery początkowe.

10.8.5 Powszechne użycie pól

Przygotowując nagłówek TCP do transmisji, w polu wskazany jest numer sekwencyjny pierwszego oktetu przesyłanych danych kolejny numer(Numer sekwencji).

Następny numer oktetu oczekiwany od partnera połączenia jest wprowadzany w polu potwierdzenie(Numer potwierdzenia), gdy bit ACK jest ustawiony na 1. Pole okno(Okno) dotyczy bieżącego rozmiaru okna odbiorczego. To pole zawiera liczba bajtów z numeru potwierdzenia, które można zaakceptować... Zauważ, że ta wartość pozwala na precyzyjną kontrolę przepływu danych. Za pomocą tej wartości partner wskazuje rzeczywisty stan okna odbiorczego podczas sesji giełdowej.

Jeśli aplikacja wskazuje operację wypychania TCP, flaga PUSH jest ustawiona na 1. Odbierający TCP MUSI odpowiedzieć na tę flagę, szybko dostarczając dane do aplikacji, gdy tylko nadawca chce je wysłać.

Flaga URGENT, jeśli jest ustawiona na 1, oznacza pilny transfer danych, a odpowiedni wskaźnik MUSI odnosić się do ostatniego oktetu pilnych danych. Typowym zastosowaniem pilnych danych jest wysyłanie z terminala sygnałów anulowania lub przerwania.

Pilne dane są często nazywane informacje poza pasmem(poza pasmem). Termin ten jest jednak nieprecyzyjny. Przyspieszone dane są wysyłane w zwykłym strumieniu TCP, chociaż niektóre implementacje mogą mieć specjalne mechanizmy nakazujące aplikacji otrzymanie pilnych danych, a aplikacja musi sprawdzić zawartość pilnych danych, zanim dotrą wszystkie bajty wiadomości.

Flaga RESET jest ustawiona na 1, aby przerwać połączenie. Ta sama flaga jest ustawiana w odpowiedzi, gdy pojawia się segment, który nie jest powiązany z żadnym z bieżących połączeń TCP.

FIN jest ustawiony na 1 dla komunikatów o zamknięciu połączenia.


10.8.6 Suma kontrolna

Suma kontrolna IP dotyczy tylko nagłówka IP, a suma kontrolna TCP jest obliczana dla całego segmentu, a także pseudonagłówka wygenerowanego z nagłówka IP. Podczas obliczania sumy kontrolnej TCP odpowiednie pole jest ustawione na 0. Na ryc. 10.15 pokazuje pseudonagłówek bardzo podobny do tego używanego w sumie kontrolnej UDP.


Ryż. 10.15. Pole pseudonagłówka jest zawarte w sumie kontrolnej TCP

Długość TCP jest obliczana przez dodanie długości nagłówka TCP do długości danych. Suma kontrolna TCP to obowiązkowy, a nie jak UDP. Suma kontrolna odebranego segmentu jest najpierw obliczana przez odbiorcę, a następnie porównywana z zawartością pola sumy kontrolnej nagłówka TCP. Jeśli wartości się nie zgadzają, segment jest odrzucany.

10.9 Przykładowy segment TCP

Ryż. 10.16, protokół analizatora Wąchacz według Network General, jest sekwencją segmentów TCP. Pierwsze trzy segmenty nawiązują połączenie między klientem a serwerem Telnet... Ostatni segment zawiera 12 bajtów danych.


Ryż. 10.16. Wyświetlanie nagłówka TCP przez Sniffer Analyzer

Analizator Wąchacz tłumaczy większość wartości na dziesiętne. Jednak wartości flag są wyprowadzane w postaci szesnastkowej. Flaga o wartości 12 to 010010. Suma kontrolna jest również wyświetlana w postaci szesnastkowej.

10.10 Wsparcie sesji

10.10.1 Sondowanie okien

Szybki nadawca i powolny odbiorca mogą utworzyć 0 bajtowe okno odbioru. Ten wynik nazywa się zamykanie okna(Zamknij okno). Gdy jest wolne miejsce na aktualizację rozmiaru okna odbioru, używane jest ACK. Jeśli jednak taka wiadomość zostanie utracona, obie strony będą musiały czekać w nieskończoność.

Aby uniknąć takiej sytuacji, nadawca ustawia zapisany timer(utrzymujący się zegar), gdy okno jest zamknięte. Wartość timera to limit czasu retransmisji. Pod koniec odliczania do partnera wysyłany jest segment brzmiące okno(Sonda okienkowa; niektóre implementacje zawierają również dane). Sondowanie powoduje, że peer wysyła z powrotem potwierdzenie ACK, które raportuje bieżący stan okna.

Jeśli okno nadal ma rozmiar zerowy, wartość przechowywanego zegara jest podwajana. Ten proces jest powtarzany, aż licznik osiągnie maksimum 60 sekund. TCP będzie nadal wysyłać komunikaty sondujące co 60 sekund — do momentu otwarcia okna, zakończenia procesu przez użytkownika lub przekroczenia limitu czasu aplikacji.

10.11 Wylogowanie

10.11.1 Limit czasu

Partner połączenia może ulec awarii lub zostać całkowicie przerwany z powodu awarii bramy lub komunikacji. Istnieje kilka mechanizmów zapobiegających ponownemu wysyłaniu danych przez protokół TCP.

Po osiągnięciu pierwszego progu retransmisji (przekazywania), TCP instruuje IP, aby sprawdził uszkodzony router i jednocześnie informuje aplikację o problemie. TCP kontynuuje wysyłanie danych do momentu osiągnięcia drugiej wartości granicznej, a dopiero potem kończy połączenie.

Oczywiście, zanim to się stanie, może pojawić się komunikat ICMP z informacją, że miejsce docelowe jest z jakiegoś powodu nieosiągalne. W niektórych implementacjach nawet wtedy TCP będzie nadal próbował dotrzeć do miejsca docelowego, aż upłynie limit czasu (po którym problem może zostać rozwiązany). Następnie aplikacja jest informowana, że ​​miejsce docelowe jest nieosiągalne.

Aplikacja może ustawić własny limit czasu dostarczenia danych i wykonać własne operacje na końcu tego interwału. Połączenie jest zwykle rozłączone.

10.11.2 Utrzymanie połączenia

Gdy niekompletne połączenie przez długi czas ma dane do przesłania, otrzymuje stan nieaktywny. W okresie bezczynności może nastąpić awaria lub przerwa w sieci linie fizyczne Komunikacja. Gdy tylko sieć zacznie ponownie działać, partnerzy będą kontynuować wymianę danych bez przerywania sesji komunikacyjnej. Ta strategia była zgodna z wymogami Departamentu Obrony.

Jednak każde połączenie - aktywne lub nieaktywne - zajmuje dużo pamięci komputera. Niektórzy administratorzy muszą zwracać nieużywane zasoby do systemów. Dlatego wiele implementacji TCP jest w stanie wysłać wiadomość o utrzymywanie połączenia(keep-alive), testowanie nieaktywnych połączeń. Takie wiadomości są okresowo wysyłane do partnera w celu weryfikacji jego istnienia w sieci. Komunikaty ACK powinny być odbierane w odpowiedzi. Korzystanie z wiadomości podtrzymujących jest opcjonalne. Jeśli system ma taką możliwość, aplikacja może ją anulować własnymi środkami. Szacowany okres domyślny limit czasu na utrzymanie połączenia wynosi pełne dwie godziny!

Przypomnijmy, że aplikacja może ustawić własny timer, zgodnie z którym na swoim poziomie podejmie decyzję o zerwaniu połączenia.

10.12 Wydajność

Jak wydajny jest TCP? Na wydajność zasobów wpływa wiele czynników, z których głównymi są pamięć i przepustowość (patrz Rysunek 10.17).


Ryż. 10.17. Czynniki wydajności TCP

Przepustowość i opóźnienie w używanej sieci fizycznej poważnie ograniczą przepustowość. Słaba jakość transferu danych skutkuje dużą ilością porzuconych datagramów, co powoduje retransmisję iw rezultacie zmniejsza wydajność przepustowości.

Strona odbierająca musi zapewnić wystarczającą ilość miejsca w buforze, aby umożliwić nadawcy wysyłanie danych bez przerw. Jest to szczególnie ważne w przypadku sieci o dużym opóźnieniu, w których występuje długi odstęp czasu między wysłaniem danych a otrzymaniem ACK (oraz podczas negocjowania rozmiaru okna). Aby utrzymać stabilny strumień danych ze źródła, strona odbierająca musi mieć okno co najmniej iloczynu przepustowości i opóźnienia.

Na przykład, jeśli źródło może wysyłać dane z prędkością 10 000 bajtów/s, a zwrócenie ACK zajmuje 2 sekundy, to z drugiej strony należy zapewnić okno odbiorcze co najmniej 20 000 bajtów, w przeciwnym razie przepływ danych nie będzie ciągły. Bufor odbioru o wielkości 10 000 bajtów zmniejszy przepustowość o połowę.

Innym ważnym czynnikiem wpływającym na wydajność jest zdolność hosta do reagowania na zdarzenia o wysokim priorytecie i szybkiego wykonywania przełączanie kontekstu, tj. wykonać niektóre operacje i przejść do innych. Host może interaktywnie obsługiwać wielu lokalnych użytkowników, wsadowo procesy w tle i dziesiątki jednoczesnych połączenia komunikacyjne... Przełączanie kontekstu umożliwia obsługę wszystkich tych operacji przy jednoczesnym ukryciu obciążenia systemu. Implementacje integrujące protokół TCP/IP z jądrem systemu operacyjnego mogą znacznie zmniejszyć obciążenie związane z przełączaniem kontekstu.

Zasoby procesora komputera są wymagane do przetwarzania nagłówków TCP. Jeśli procesor nie jest w stanie szybko obliczyć sum kontrolnych, spowolni szybkość przesyłania danych w sieci.

Ponadto programiści powinni rozważyć ułatwienie konfiguracji parametrów TCP, tak aby administrator sieci mógł dostosować je do swoich lokalnych wymagań. Na przykład możliwość dostosowania rozmiaru bufora do przepustowości i opóźnienia sieci znacznie poprawi wydajność. Niestety wiele wdrożeń nie przykłada wystarczającej uwagi do tego zagadnienia i nie zakodowuje na stałe parametrów komunikacji.

Załóżmy, że środowisko sieciowe jest idealne: zasobów jest wystarczająca ilość, a przełączanie kontekstu jest szybsze niż kowboje wyciągający rewolwery. Czy uzyskasz doskonałą wydajność?

Nie zawsze. Ważna jest również jakość tworzenia oprogramowania TCP. Wiele problemów z wydajnością zostało zdiagnozowanych i rozwiązanych na przestrzeni lat w różnych implementacjach TCP. Możemy założyć, że najlepsze będą oprogramowanie, który jest zgodny z RFC 1122, który określa wymagania dla warstwy komunikacyjnej hostów internetowych.

Równie ważny jest wyjątek oraz zastosowanie algorytmów Jacobsona, Kerna i Partridge'a (te interesujące algorytmy zostaną omówione poniżej).

Twórcy oprogramowania mogą czerpać znaczne korzyści, tworząc programy, które eliminują niepotrzebne transfery niewielkich ilości danych i mają wbudowane zegary zwalniające zasoby sieciowe, które nie są obecnie używane.

10.13 Algorytmy poprawiające wydajność

Przechodząc do dość złożonej części TCP, przyjrzymy się mechanizmom poprawy wydajności i rozwiązywania wąskich gardeł przepustowości. W tej sekcji omówiono następujące zagadnienia:

Powolny start(wolny start) zapobiega wykorzystywaniu dużej części ruchu sieciowego w nowej sesji, co może prowadzić do narzutu.

■ Odzyskiwanie z syndrom głupkowatego okna(syndrom głupiego okna) zapobiega przeciążaniu sieci wiadomościami przez źle zaprojektowane aplikacje.

Opóźnione potwierdzenie(opóźnione ACK) zmniejsza przeciążenie, zmniejszając liczbę niezależnych wiadomości potwierdzających przesyłanie dalej.

Obliczony limit czasu retransmisji(obliczanie limitu czasu retransmisji) opiera się na negocjowaniu czasu sesji w czasie rzeczywistym, redukując niepotrzebne retransmisje, ale nie powodując dużych opóźnień dla naprawdę potrzebnych wymian danych.

■ Zwolnij przekazywanie TCP, gdy przeciążenia w sieci umożliwia routerom powrót do ich pierwotnego trybu i współdzielenie zasobów sieciowych dla wszystkich sesji.

■ Wysyłanie zduplikowane ACK(zduplikowane ACK) podczas odbierania segmentu poza kolejnością, umożliwia równorzędnym ponowne wysłanie przed przekroczeniem limitu czasu.

10.13.1 Powolny start

Jeśli wszystkie domowe urządzenia elektryczne zostaną włączone w domu w tym samym czasie, nastąpi przeciążenie sieci elektrycznej. V sieć komputerowapowolny start zapobiega przepaleniu bezpieczników sieciowych.

Nowe połączenie, które natychmiast uruchamia przesyłanie dużych ilości danych w już obciążonej sieci, może prowadzić do problemów. Ideą powolnego startu jest zapewnienie pomyślnego uruchomienia nowego połączenia, przy jednoczesnym powolnym zwiększaniu szybkości przesyłania danych zgodnie z rzeczywistym obciążeniem sieci. Nadawca jest ograniczony rozmiarem okna ładowania, a nie dużego okna odbioru.

Okno ładowania(okno przeciążenia) zaczyna się od rozmiaru 1 segmentu. Dla każdego segmentu z pomyślnie odebranym ACK okno ładowania jest zwiększane o 1 segment, o ile pozostaje ono mniejsze niż okno odbioru. Jeśli sieć nie jest przeciążona, okno ładowania stopniowo osiągnie rozmiar okna odbiorczego. W normalnych warunkach przekazywania te okna będą miały ten sam rozmiar.

Zauważ, że powolny start nie jest taki wolny. Po pierwszym ACK rozmiar okna ładowania jest równy 2 segmentom, a po pomyślnym odebraniu ACK dla dwóch segmentów rozmiar może wzrosnąć do 8 segmentów. Innymi słowy, rozmiar okna rośnie wykładniczo.

Załóżmy, że zamiast otrzymania ACK, wystąpiła sytuacja przekroczenia limitu czasu. Zachowanie okna ładowania w tym przypadku zostało omówione poniżej.

10.13.2 Syndrom bezradnego okna

W pierwszych wdrożeniach TCP/IP programiści zmierzyli się ze zjawiskiem syndrom głupkowatego okna(Syndrom Silly Window - SWS), który pojawiał się dość często. Aby zrozumieć zachodzące wydarzenia, rozważ następujący scenariusz, który prowadzi do niepożądanych konsekwencji, ale jest całkiem możliwe:

1. Aplikacja wysyłająca szybko przesyła dane.

2. Aplikacja odbierająca odczytuje 1 bajt danych z bufora wejściowego (tj. powoli).

3. Bufor wejściowy szybko się zapełnia po odczycie.

4. Aplikacja odbierająca odczytuje 1 bajt, a TCP wysyła potwierdzenie ACK oznaczające „Mam wolne miejsce na 1 bajt danych”.

5. Aplikacja wysyłająca wysyła przez sieć 1-bajtowy pakiet TCP.

6. Odbierający TCP wysyła ACK oznaczające „Dziękuję. Otrzymałem pakiet i nie mam już wolnego miejsca”.

7. Aplikacja odbierająca ponownie odczytuje 1 bajt i wysyła potwierdzenie ACK, a cały proces się powtarza.

Powolna aplikacja odbierająca czeka długo na przybycie danych i nieustannie przesuwa otrzymane informacje do lewej krawędzi okna, wykonując całkowicie bezużyteczną operację, która generuje dodatkowy ruch online.

Oczywiście sytuacje z życia nie są tak ekstremalne. Szybki nadawca i wolny odbiorca wymieniają małe (w stosunku do maksymalnego rozmiaru segmentu) porcje danych i przełączają się na prawie pełne okno odbioru. Na ryc. 10.18 pokazuje warunki pojawienia się syndromu „głupkowatego okna”.


Ryż. 10.18. Odbierz bufor okna z bardzo małą wolną przestrzenią

Ten problem nie jest trudny do rozwiązania. Gdy tylko okno odbioru zmniejszy się mniej niż podany rozmiar docelowy, TCP zaczyna oszukiwać nadawcę. W takiej sytuacji protokół TCP nie powinien kierować nadawcy do dodatkowy miejsce w oknie, gdy aplikacja odbierająca odczytuje dane z bufora małymi porcjami. Zamiast tego uwolnione zasoby powinny być utrzymywane w tajemnicy przed nadawcą, dopóki nie będzie ich wystarczająco dużo. Zalecany rozmiar to jeden segment, chyba że cały bufor wejściowy zawiera jeden segment (w tym ostatnim przypadku używany jest rozmiar równy połowie bufora). Rozmiar docelowy, który ma być zgłaszany przez TCP, może być wyrażony jako:

minimum (1/2 bufora wejściowego, maksymalny rozmiar segmentu)

TCP zaczyna oszukiwać, gdy rozmiar okna staje się mniejszy niż ten rozmiar, i powie prawdę, gdy rozmiar okna nie jest mniejszy niż wartość uzyskana przez formułę. Należy pamiętać, że nadawca nie ponosi żadnej szkody, ponieważ aplikacja odbierająca nadal nie byłaby w stanie przetworzyć większości oczekiwanych danych.

Proponowane rozwiązanie można łatwo zweryfikować w powyższym przypadku za pomocą wyjścia ACK dla każdego z odebranych bajtów. Ta sama metoda jest również odpowiednia w przypadku, gdy bufor wejściowy może przechowywać kilka segmentów (co często ma miejsce w praktyce). Szybki nadawca wypełni bufor wejściowy, ale odbiorca wskaże, że nie ma wolnego miejsca na umieszczenie informacji i nie otworzy tego zasobu, dopóki jego rozmiar nie osiągnie całego segmentu.

10.13.3 Algorytm Nagle'a

Nadawca powinien, niezależnie od odbiorcy, wykluczyć transmisję bardzo krótkich segmentów, gromadząc dane przed wysłaniem. Algorytm Nagle'a realizuje bardzo prosty pomysł na zmniejszenie liczby krótkich datagramów przesyłanych przez sieć.

Algorytm zaleca opóźnienie przesyłania danych (i wypychanie) poprzez oczekiwanie na potwierdzenie ACK z wcześniej przesłanych danych. Zgromadzone dane są wysyłane po otrzymaniu potwierdzenia ACK na wcześniej przesłaną informację lub po odebraniu danych w rozmiarze pełnego segmentu do wysłania lub po upływie limitu czasu. Tego algorytmu nie należy używać w aplikacjach czasu rzeczywistego, które muszą przesyłać dane tak szybko, jak to możliwe.

10.13.4 Opóźnione ACK

Innym mechanizmem zwiększania wydajności jest metoda opóźnienia ACK. Zmniejszenie liczby ACK zmniejsza przepustowość, którą można wykorzystać do przekazywania innego ruchu. Jeśli peer TCP opóźnia wysłanie ACK, wtedy:

■ Odbiór wielu segmentów można potwierdzić jednym potwierdzeniem ACK.

■ Aplikacja odbierająca może odebrać pewną ilość danych w określonym przedziale czasu; nagłówek wyjściowy może być zawarty w ACK i nie wymaga generowania osobnego komunikatu.

Aby uniknąć opóźnień podczas wysyłania strumienia pełnowymiarowych segmentów (na przykład podczas wymiany plików), potwierdzenie ACK powinno być wysyłane przynajmniej co drugi pełny segment.

Wiele implementacji używa limitu czasu 200ms. Ale opóźnione ACK nie spowalnia kursu walutowego. Po nadejściu krótkiego segmentu w buforze wejściowym jest jeszcze wystarczająco dużo wolnego miejsca na odebranie nowych danych, a nadawca może kontynuować wysyłanie (dodatkowo retransmisja jest zwykle znacznie wolniejsza). Jeśli nadejdzie cały segment, musisz odpowiedzieć na niego komunikatem ACK w tej samej sekundzie.

10.13.5 Limit czasu retransmisji

Po wysłaniu segmentu TCP ustawia zegar i monitoruje nadejście ACK. Jeśli w ciągu limitu czasu nie zostanie odebrane żadne ACK, TCP ponownie przesyła segment (przekaźnik). Jaka powinna być jednak przerwa?

Jeśli będzie za krótki, nadawca wypełni sieć przesyłając niepotrzebne segmenty, które powielają już wysłane informacje. Zbyt długi limit czasu uniemożliwi szybkie naprawianie segmentów, które są naprawdę złe podczas przesyłania, co zmniejszy przepustowość.

Jak wybrać odpowiednią ilość czasu na przerwę? Wartość, która jest dobra dla szybkiej sieci LAN, nie jest dobra w przypadku połączenia zdalnego z wieloma trafieniami. Oznacza to, że zasada „jedna wartość dla wszystkich warunków” jest wyraźnie nieodpowiednia. Co więcej, nawet w przypadku istniejącego konkretnego połączenia warunki sieciowe mogą się zmienić, a opóźnienia mogą się zwiększać lub zmniejszać.

Algorytmy Jacobsona, Kerna i Partridge'a (opisane w artykułach) , Van Jacobson i Poprawa szacowania czasu podróży w obie strony w niezawodnych protokołach transportowych, Karn i Partridge) umożliwiają TCP dostosowywanie się do zmieniających się warunków sieciowych. Te algorytmy są zalecane do stosowania w nowych implementacjach. Omówimy je pokrótce poniżej.

Zdrowy rozsądek podpowiada, że ​​najlepszą podstawą do oszacowania prawidłowego czasu oczekiwania dla konkretnego połączenia może być: Czas cyklu(czas podróży w obie strony) jako odstęp czasu pomiędzy wysłaniem danych a otrzymaniem potwierdzenia ich otrzymania.

Dobre decyzje dla następujących wielkości można uzyskać na podstawie podstawowych statystyk (patrz Rysunek 10.19), które mogą pomóc w obliczeniu limitu czasu. Nie należy jednak polegać na średnich, ponieważ ponad połowa szacunków będzie wyższa od średniej. Patrząc na kilka odchyleń, można uzyskać dokładniejsze szacunki, biorąc pod uwagę rozkład normalny i skracając zbyt długi czas oczekiwania na retransmisję.


Ryż. 10.19. Rozkład czasów cykli

Nie ma potrzeby wykonywania dużej ilości obliczeń, aby uzyskać formalne matematyczne oszacowania odchyleń. Szacunki przybliżone można zastosować na podstawie wartości bezwzględnej różnicy między ostatnią wartością a oszacowaniem średnim:

Ostatnie odchylenie = | Ostatni cykl - Średnia |

Innym czynnikiem, który należy wziąć pod uwagę przy obliczaniu prawidłowego limitu czasu, jest zmiana czasu cyklu spowodowana bieżącymi warunkami sieciowymi. To, co wydarzyło się w sieci w ostatniej chwili, jest ważniejsze niż to, co wydarzyło się godzinę temu.

Załóżmy, że obliczasz średnią cyklu dla bardzo długiej sesji. Mimo że sieć była początkowo lekko obciążona i ustaliliśmy 1000 małych wartości, nastąpił wzrost ruchu ze znacznym wzrostem opóźnień.

Na przykład, jeśli 1000 wartości dało średnią 170 jednostek, a potem zmierzono 50 wartości ze średnią 282, to aktualna średnia wyniesie:

170 × 1000/1050 + 282 × 50/1050 = 175

Bardziej rozsądna byłaby wartość wygładzony czas cyklu(Smoothed Round-Trip Time - SRTT), który uwzględnia priorytet późniejszych wartości:

Nowe SRTT = (1 - α) × (stare SRTT) + α × Wartość ostatniego cyklu

Wartość α wynosi od 0 do 1. Zwiększ powoduje większy wpływ aktualnego czasu cyklu na wygładzoną średnią. Ponieważ komputery mogą szybko dzielić przez potęgi 2, przesuwając liczby binarne w prawo, α jest zawsze wybierane jako (1/2) n (zwykle 1/8), więc:

Nowy SRTT = 7/8 × stary SRTT + 1/8 × Czas ostatniego cyklu

Tabela 10.2 pokazuje, w jaki sposób formuła SRTT dostosowuje się do bieżącej wartości SRTT wynoszącej 230, gdy zmiana stanu sieci powoduje progresywny wzrost czasu cyklu (przy założeniu, że nie występuje przekroczenie limitu czasu). Wartości w kolumnie 3 są używane jako wartości w kolumnie 1 dla następna linia tabele (tj. jak stary SRTT).


Tabela 10.2 Obliczanie wygładzonego czasu cyklu

Stary SRTT Najnowsze RTT (7/8) × (stary SRTT) + (1/8) × (RTT)
230.00 294 238.00
238.00 264 241.25
241.25 340 253.59
253.59 246 252.64
252.64 201 246.19
246.19 340 257.92
257.92 272 259.68
259.68 311 266.10
266.10 282 268.09
268.09 246 265.33
265.33 304 270.16
270.16 308 274.89
274.89 230 269.28
269.28 328 276.62
276.62 266 275.29
275.29 257 273.00
273.00 305 277.00

Teraz pojawia się kwestia wyboru wartości limitu czasu retransmisji. Analiza czasów cykli wskazuje na znaczne odchylenie tych wartości od aktualnej średniej. Sensowne jest ustalenie limitu wielkości odchyleń (odchyłek). Dobre wartości limitu czasu retransmisji (ang. Retransmission TimeOut - RTO w standardach RFC) podaje następujący wzór z wygładzonym ograniczeniem odchylenia (SDEV):

T = Limit czasu retransmisji = SRTT + 2 × SDEV

T = SRTT + 4 × SDEV

Aby obliczyć SDEV, najpierw określ wartość bezwzględną odchylenia prądu:

ODCH = | Czas ostatniego cyklu — stary SRTT |

Formuła wygładzająca jest następnie używana do uwzględnienia ostatniej wartości:

Nowe SDEV = 3/4 × stare SDEV + 1/4 × DEV

Pozostaje jedno pytanie - jakie są wartości początkowe? Zalecana:

Początkowy limit czasu = 3 s

Początkowy SRTT = 0

Początkowy SDEV = 1,5 s

Van Jacobson zdefiniował szybki algorytm, który bardzo skutecznie oblicza limit czasu retransmisji.

10.13.6 Przykładowe statystyki

Jak dobrze będzie działać wyliczony powyżej limit czasu? Zaobserwowano znaczny wzrost wydajności, gdy uzyskana wartość została zrealizowana. Przykładem mogą być statystyki zespołu netstat otrzymane w systemie Tygrys- serwer internetowy, do którego dostęp ma wiele hostów z całego świata.


1510769 pakietów (314955304 bajtów) odebranych w sekwencji

System Tygrys retransmitowano mniej niż 2,5% segmentów danych TCP. W przypadku półtora miliona segmentów danych przychodzących (reszta to wyłącznie komunikaty ACK) zduplikowano tylko 0,6%. Należy pamiętać, że poziom straty w danych wejściowych w przybliżeniu odpowiada poziomowi segmentów wyjściowych. Tak więc bezużyteczny ruch retransmisyjny stanowi około 0,6% całkowitego ruchu.

10.13.7 Obliczenia po ponownym przesłaniu

Powyższe wzory wykorzystują wartość czasu cyklu jako interwał pomiędzy wysłaniem segmentu a otrzymaniem potwierdzenia. Załóżmy jednak, że żadne potwierdzenie nie zostanie odebrane w okresie limitu czasu i dane muszą zostać ponownie wysłane.

Algorytm Kerna zakłada, że ​​w tym przypadku nie należy zmieniać czasu cyklu. Aktualna wygładzona wartość czasu cyklu i wygładzone odchylenie zachować ich wartości do momentu otrzymania potwierdzenia wysłania określonego segmentu bez jego ponownego wysyłania. W tym momencie obliczenia są wznawiane na podstawie zapisanych wartości i nowych pomiarów.

10.13.8 Czynności po retransmisji

Ale co się dzieje przed otrzymaniem potwierdzenia? Po retransmisji zachowanie TCP zmienia się radykalnie, głównie z powodu utraty danych w wyniku przeciążenia sieci. Dlatego reakcją na ponowne przesłanie danych będzie:

■ Zmniejszenie szybkości ponownej wysyłki

■ Zmniejsz przeciążenie sieci poprzez zmniejszenie ogólnego ruchu

10.13.9 Hamowanie wykładnicze

Po retransmisji interwał limitu czasu jest podwajany. Co się jednak stanie, jeśli licznik czasu ponownie się przepełni? Dane zostaną wysłane ponownie, a okres retransmisji zostanie ponownie podwojony. Ten proces nazywa się wykładnicze spowolnienie(wykładniczy odczekiwanie).

Jeśli awaria sieci będzie się utrzymywać, czas oczekiwania zostanie podwojony, aż do osiągnięcia ustawionej wartości maksymalnej (zwykle 1 minuta). Po upływie limitu czasu można wysłać tylko jeden segment. Przekroczenie limitu czasu występuje również, gdy przekroczona zostanie z góry określona wartość liczby transferów danych bez otrzymania potwierdzenia ACK.

10.13.10 Zmniejszenie przeciążenia poprzez zmniejszenie ilości danych przesyłanych przez sieć

Zmniejszenie ilości przesyłanych danych jest nieco bardziej złożone niż mechanizmy omówione powyżej. Zaczyna działać, jak wspomniany już powolny start. Ponieważ jednak dla poziomu ruchu ustanowiono granicę, co początkowo może prowadzić do problemów, kurs wymiany w rzeczywistości zwolni ze względu na zwiększenie rozmiaru okna obciążenia dla jednego segmentu. Musisz ustawić wartości graniczne, aby naprawdę zmniejszyć prędkość wysyłania. Najpierw obliczany jest próg zagrożenia:

Granica — minimum 1/2 (bieżące okno ładowania, okno odbioru partnera)

Jeśli uzyskana wartość ma więcej niż dwa segmenty, jest używana jako granica. W przeciwnym razie granica jest ustawiona na dwa segmenty. Kompletny algorytm odzyskiwania wymaga:

■ Ustaw rozmiar okna ładowania na jeden segment.

S Dla każdego otrzymanego ACK zwiększ okno obciążenia o jeden segment, aż do osiągnięcia granicy (bardzo podobnie do mechanizmu powolnego startu).

■ Następnie, przy każdym odebranym ACK, dodaj mniejszą wartość do okna obciążenia, które jest wybierane na podstawie szybkości wzrostu w jednym segmencie dla czasu cyklu (wzrost jest obliczany jako MSS / N, gdzie N jest wielkością okno obciążenia w segmentach).

Idealny scenariusz może uprościć działanie mechanizmu naprawczego. Załóżmy, że okno odbierania partnera (i bieżące okno ładowania) miało rozmiar 8 segmentów przed wykryciem limitu czasu, a granica została zdefiniowana jako 4 segmenty. Jeśli aplikacja odbierająca natychmiast odczytuje dane z bufora, okno odbierania pozostaje na 8 segmentach.

■ Wysyłany jest 1 segment (okno ładowania = 1 segment).

■ Odebrane ACK — wysyłane są 2 segmenty.

■ ACK dla 2 segmentów odebranych — 4 segmenty są wysyłane (osiągnięto granicę).

■ Odebrano ACK dla 4 segmentów. Wysyłanych jest 5 segmentów.

■ ACK odebrane dla 5 segmentów. Wysyłanych jest 6 segmentów.

■ Odebrano ACK dla 6 segmentów. Wysyłanych jest 7 segmentów.

■ Odebrano ACK dla 7 segmentów. Wysyłanych jest 8 segmentów (okno wczytywania ponownie ma taki sam rozmiar jak okno odbioru).

Ponieważ potwierdzenie wszystkich wysłanych danych jest wymagane podczas limitu czasu retransmisji, proces jest kontynuowany, dopóki okno ładowania nie osiągnie rozmiaru okna odbioru. Zachodzące wydarzenia pokazano na ryc. 10.20. Rozmiar okna rośnie wykładniczo, podwajając się w okresie wolnego startu, a po osiągnięciu granicy rośnie liniowo.


Ryż. 10.20. Ograniczanie szybkości transferu podczas zatorów

10.13.11 Zduplikowane potwierdzenia ACK

W niektórych realizacjach wykorzystywana jest opcjonalna funkcja – tzw szybka ponowna wysyłka(szybka retransmisja) - w celu przyspieszenia retransmisji danych w określonych warunkach. Jego główna idea wiąże się z wysyłaniem przez odbiorcę dodatkowych ACK, wskazujących na lukę w odebranych danych.

Po otrzymaniu segmentu poza kolejnością, odbiorca odsyła potwierdzenie ACK wskazujące na pierwszy bajt. Stracony dane (patrz Rysunek 10.21).


Ryż. 10.21. Zduplikowane potwierdzenia ACK

Nadawca nie dokonuje natychmiastowej retransmisji danych, ponieważ IP może normalnie dostarczyć dane do odbiorcy bez sekwencji wysyłania. Ale gdy odebranych zostanie kilka dodatkowych ACK dla zduplikowanych danych (na przykład trzy), brakujący segment zostanie wysłany bez oczekiwania na wygaśnięcie limitu czasu.

Należy zauważyć, że każde zduplikowane potwierdzenie ACK oznacza odbiór segmentu danych. Kilka zduplikowanych pakietów ACK informuje, że sieć jest w stanie dostarczyć wystarczającą ilość danych, a zatem nie jest przeciążona. W ramach całego algorytmu wykonywane jest niewielkie zmniejszenie rozmiaru okna obciążenia przy rzeczywistym wzroście ruchu w sieci. W takim przypadku proces radykalnej zmiany rozmiaru podczas przywracania pracy nie ma zastosowania.

Zgodnie ze standardem Wymagania hosta(wymagania hosta) TCP powinien wykonywać ten sam powolny start, jak opisano powyżej, podczas gaszenia źródła (gaszenie źródła). Jednak zgłaszanie tego nie jest ukierunkowane ani skuteczne, ponieważ połączenie odbierające tę wiadomość może nie generować zbyt dużego ruchu. Aktualna specyfikacja Wymagania dotyczące routera(wymagania dotyczące routera) wskazuje, że routery nie powinieneś wysyłać wiadomości o wygaszeniu źródła.

10.13.13 Statystyki TCP

Na koniec spójrzmy na komunikaty statystyczne polecenia netstat, aby zobaczyć działanie wielu opisanych powyżej mechanizmów.

Segmenty to nazwane pakiety.
879137 pakietów danych (226966295 bajtów)
21815 pakietów danych (8100927 bajtów) retransmitowanych
Ponowna wysyłka.
132957 pakiety tylko potwierdzające (104216 opóźnione)
Zauważamy dużą liczbę

opóźnione potwierdzenie.

Sondowanie otwarcia okna

zerowy rozmiar.

Są to komunikaty SYN i FIN.
762469 potwierdzeń (dla 226904227 bajtów)
Powiadomienie o nadchodzących przesyłkach

poza kolejnością.

1510769 pakietów (314955304 bajtów)
9006 całkowicie zduplikowanych pakietów (867042 bajtów)
Wynik limitu czasu, gdy rzeczywisty

dostarczenie danych.

74 pakiety z jakimś dup. dane (12193 bajty zduplikowane)
Dla większej wydajności

niektóre dane zostały przepakowane w celu uwzględnienia dodatkowych bajtów przy ponownym przesłaniu.

13452 nieuporządkowane pakiety (2515087 bajtów)
530 pakietów (8551 bajtów) danych po oknie
Być może te dane były

zawarte w wiadomościach wykrywających.

402 pakiety odebrane po zamknięciu
To są kolejne powtórki

wysyłanie.

108 odrzucone za złe sumy kontrolne
Nieprawidłowa suma kontrolna TCP.
0 odrzucone dla złych pól przesunięcia nagłówka
7 odrzucone, ponieważ pakiet jest za krótki
Ustanowiono 14677 połączeń (w tym akceptuje)
Zamknięto 18929 połączeń (w tym 643 zrzuty)
Odrzucono 4100 połączeń embrionalnych
572187 segmentów zaktualizowanych rtt (z 587397 prób)
Nieudane próby zmiany

czas cyklu, ponieważ ACK nie zdążyło dotrzeć przed upływem limitu czasu,

26 połączeń zerwanych po przekroczeniu limitu czasu rexmit
Kolejne nieudane próby

ponowne wysłanie, co oznacza utratę połączenia.

Limity czasu sondowania

zerowe okno.

Limity czasu realizacji transakcji

zerwane połączenie.

472 połączenia zerwane przez utrzymywanie aktywności

10.14 Zgodność z wymaganiami programisty

Obecny standard TCP wymaga, aby implementacje przestrzegały procedury powolnego uruchamiania podczas inicjowania połączenia i używały algorytmów Kerna i Jacobsona do oszacowania limitu czasu retransmisji i zarządzania obciążeniem. Testy wykazały, że te mechanizmy prowadzą do znacznej poprawy wydajności.

Co się stanie, jeśli zainstalujesz system, który nie spełnia tych standardów? Nie będzie w stanie zapewnić odpowiedniej wydajności dla własnych użytkowników i będzie słabym sąsiadem dla innych systemów w sieci, uniemożliwiając przywrócenie normalnego działania po chwilowym przeciążeniu i generując nadmierny ruch, który powoduje utratę datagramów.

10.15 Bariery dla wydajności

TCP udowodnił swoją elastyczność, działając w sieciach z kursami wymiany setek lub milionów bitów na sekundę. Protokół ten umożliwił osiągnięcie dobrych wyników w nowoczesnych sieci lokalne z topologiami Ethernet, Token-Ring i Fibre Distributed Data Interface (FDDI) oraz dla łączy o niskiej prędkości lub łączy na duże odległości (takich jak łącza satelitarne).

Protokół TCP został zaprojektowany tak, aby reagować na ekstremalne warunki, takie jak przeciążenie sieci. Jednak aktualna wersja protokołu ma funkcje, które ograniczają wydajność w obiecujące technologie które oferują przepustowość w setkach i tysiącach megabajtów. Aby zrozumieć pojawiające się problemy, rozważ prosty (choć nierealistyczny) przykład.

Załóżmy, że podczas przenoszenia pliku między dwoma systemami chcesz jak najefektywniej wymieniać ciągły strumień. Załóżmy, że:

■ Maksymalny rozmiar segmentu docelowego to 1 KB.

■ Okno odbioru — 4 KB.

Przepustowość pozwala na wysłanie dwóch segmentów w ciągu 1 sekundy.

■ Aplikacja odbierająca zużywa dane w momencie nadejścia.

Wiadomości SACK docierają w ciągu 2 sekund.

Nadawca może przesyłać dane w sposób ciągły. W końcu, gdy wolumen przydzielony dla okna jest pełny, nadchodzi ACK, umożliwiające wysłanie kolejnego segmentu:

Po 2 s:

ODBIERZ SEGMENT 1, MOŻE WYSŁAĆ SEGMENT 5.
ODBIERZ SEGMENT 2, MOŻE WYSŁAĆ SEGMENT 6.
ODBIERZ SEGMENT 3, MOŻE WYSŁAĆ SEGMENT 7.
ODBIERZ SEGMENT 4, MOŻE WYSŁAĆ SEGMENT 8.

Po kolejnych 2 s:

ODBIERZ SEGMENT 5, MOŻE WYSŁAĆ SEGMENT 9.

Jeśli okno odbioru miało tylko 2 KB, nadawca musiałby czekać jedną sekundę z każdych dwóch przed wysłaniem kolejnych danych. W rzeczywistości, aby utrzymać ciągły strumień danych, okno odbioru musi mieć co najmniej:

Okno = Przepustowość × Czas cyklu

Chociaż przykład jest nieco przesadzony (aby zapewnić prostsze liczby), małe okno może prowadzić do problemów z połączeniami satelitarnymi o dużym opóźnieniu.

Przyjrzyjmy się teraz, co dzieje się z szybkimi połączeniami. Na przykład, jeśli przepustowość i szybkość transferu są mierzone przy 10 milionach bitów na sekundę, ale czas cyklu wynosi 100 ms (1/10 sekundy), to dla strumienia ciągłego okno odbioru musi przechowywać co najmniej 1 000 000 bitów, czyli ... 125 000 bajtów. Ale największa liczba, jaką można zapisać w polu nagłówka dla okna odbioru TCP, to 65 536.

Inny problem pojawia się przy dużych szybkościach transmisji, ponieważ numery sekwencyjne kończą się bardzo szybko. Jeżeli połączenie może przesyłać dane z prędkością 4 GB/s, to numery sekwencyjne powinny być aktualizowane co sekundę. Nie będzie można odróżnić starych, zduplikowanych datagramów, które zostały opóźnione o więcej niż sekundę podczas surfowania po Internecie, od nowych, świeżych danych.

Trwają nowe badania mające na celu usprawnienie TCP/IP i usunięcie powyższych barier.

10.16 Funkcje TCP

Ten rozdział skupia się na wielu cechach TCP. Najważniejsze z nich są wymienione poniżej:

■ Powiązanie portów z połączeniami

■ Inicjalizacja połączeń przez 3-stopniowe potwierdzenie

■ Wykonuje powolny start, aby uniknąć przeciążenia sieci

■ Segmentacja danych w tranzycie

■ Numeracja danych

■ Obsługa przychodzących zduplikowanych segmentów

■ Obliczanie sum kontrolnych

■ Regulacja przepływu danych przez okno odbiorcze i okno nadawcze

■ Zakończenie połączenia ustalony sposób

■ Zakończenie połączenia

■ Przekazywanie pilnych danych

■ Pozytywne potwierdzenie ponownej wysyłki

■ Obliczanie limitu czasu retransmisji

■ Zmniejszony ruch powrotny podczas przeciążenia sieci

■ Alarm przybycia niesprawnego segmentu

■ Wyczuwanie zamknięcia okienka odbiorczego

10.17 Stany TCP

Połączenie TCP przechodzi kilka etapów: połączenie jest nawiązywane poprzez wymianę wiadomości, następnie dane są wysyłane, a następnie połączenie jest zamykane za pomocą wymiany specjalnych wiadomości. Każdy krok w pracy połączenia odpowiada pewnemu stan: schorzenie to połączenie. Oprogramowanie TCP na każdym końcu połączenia stale monitoruje Stan obecny po drugiej stronie połączenia.

Poniżej pokrótce przyjrzymy się typowej zmianie stanu serwera i klienta znajdującego się na różnych końcach połączenia. Nie zamierzamy podawać wyczerpującego opisu wszystkich możliwych stanów przy przekazywaniu danych. Znajduje się w RFC 793 i w Wymagania hosta.

Podczas nawiązywania połączeń serwer i klient przechodzą przez podobne sekwencje stanów. Stany serwerów przedstawiono w Tabeli 10.3, a stany klientów przedstawiono w Tabeli 10.4.


Tabela 10.3 Sekwencja stanu serwera

Stan serwera Wydarzenie Opis
ZAMKNIĘTE (zamknięte) Fikcyjny stan przed rozpoczęciem połączenia.
Otwieranie pasywne przez aplikację serwerową.
SŁUCHAJ (śledzenie) Serwer czeka na połączenie klienta.
Serwer TCP odbiera SYN i wysyła SYN / ACK. Serwer odebrał SYN i wysłał SYN/ACK. Idzie czekać na ACK.
SYN-ODEBRANO Serwer TCP odbiera ACK.
ZAŁOŻONY (zainstalowany) Odebrano ACK, połączenie otwarte.

Tabela 10.4 Sekwencja stanu klienta

Gdyby partnerzy jednocześnie próbowali nawiązać ze sobą połączenie (co zdarza się bardzo rzadko), każdy przechodziłby przez stany ZAMKNIĘTY, SYN-WYSŁANY, SYN-ODEBRANY i USTANOWIONY.

Końcowe strony połączenia pozostają w stanie USTANOWIONY do momentu zainicjowania jednej ze stron zamknięcie połączenia, wysyłając segment FIN. Podczas normalnego zamknięcia strona inicjująca to zamknięcie przechodzi przez stany przedstawione w tabeli 10.5. Jej partner przechodzi przez stany przedstawione w tabeli 10.6.


Tabela 10.5 Sekwencja stanów strony zamykającej połączenie

Zamykanie stanów pobocznych Wydarzenie Opis
PRZYJĘTY Aplikacja lokalna prosi o zamknięcie połączenia.
TCP wysyła FIN / ACK.
FIN-CZEKAJ-1 Osoba pokrywająca czeka na odpowiedź partnera. Przypomnij sobie, że nowe dane mogą nadal napływać od partnera.
TCP odbiera ACK.
FIN-CZEKAJ-2 Strona zamykająca otrzymała od partnera ACK, ale FIN jeszcze nie nadszedł. Strona zamykająca czeka na FIN, akceptując przychodzące dane.
TCP odbiera FIN / ACK.
Wysyła potwierdzenie.
CZAS OCZEKIWANIA Połączenie jest utrzymywane w nieokreślonym stanie, aby umożliwić przybycie lub odrzucenie zduplikowanych danych lub zduplikowanych pakietów FIN, które nadal istnieją w sieci. Okres oczekiwania jest dwukrotnością maksymalnego szacowanego czasu życia segmentu.
ZAMKNIĘTE

Tabela 10.6 Kolejność państw partnerskich do zamknięcia połączenia

Status partnera Wydarzenie Opis
PRZYJĘTY TCP odbiera FIN / ACK.
ZAMKNIJ-CZEKAJ Przybył FIN.
TCP wysyła ACK.
TCP czeka, aż jego aplikacja zamknie połączenie. W tym momencie aplikacja może wysłać dość dużą ilość danych.
Aplikacja lokalna inicjuje zamykanie połączenia.
TCP wysyła FIN / ACK.
OSTATNI POTWIERDZENIE TCP czeka na ostateczne potwierdzenie ACK.
TCP odbiera ACK.
ZAMKNIĘTE Usunięto wszystkie informacje o połączeniu.

10.17.1 Analiza stanów połączeń TCP

Komenda netstat -an pozwala sprawdzić aktualny stan połączenia. Połączenia w stanach pokazano poniżej słuchać, uruchamiać, nawiązywać, zamykać oraz Czas oczekiwania.

Zwróć uwagę, że numer portu połączenia znajduje się na końcu każdego adresu lokalnego i zewnętrznego. Widać, że istnieje ruch TCP zarówno dla kolejek przychodzących, jak i wychodzących.

Pro Recv-Q Send-Q Adres lokalny Adres obcy (stan)
Tcp 0 0 128.121.50.145.25 128.252.223.5.1526 SYN_RCVD
Tcp 0 0 128.121.50.145.25 148.79.160.65.3368 USTANOWIONO
Tcp 0 0 127.0.0.1.1339 127.0.0.1.111 CZAS_OCZEKIWANIA
Tcp 0 438 128.121.50.145.23 130.132.57.246.2219 USTANOWIONO
Tcp 0 0 128.121.50.145.25 192.5.5.1.4022 CZAS_OCZEKIWANIA
Tcp 0 0 128.121.50.145.25 141.218.1.100.3968 CZAS_OCZEKIWANIA
Tcp 0 848 128.121.50.145.23 192.67.236.10.1050 USTANOWIONO
Tcp 0 0 128.121.50.145.1082 128.121.50.141.6000 USTANOWIONO
Tcp 0 0 128.121.50.145.1022 128.121.50.141.1017 USTANOWIONO
Tcp 0 0 128.121.50.145.514 128.121.50.141.1020 ZAMKNIJ_CZEKAJ
Tcp 0 1152 128.121.50.145.119 192.67.239.23.3572 USTANOWIONO
Tcp 0 0 128.121.50.145.1070 192.41.171.5.119 CZAS_OCZEKIWANIA
Tcp 579 4096 128.121.50.145.119 204.143.19.30.1884 USTANOWIONO
Tcp 0 0 128.121.50.145.119 192.67.243.13.3704 USTANOWIONO
Tcp 0 53 128.121.50.145.119 192.67.236.218.2018 FIN_WAIT_1
Tcp 0 0 128.121.50.145.119 192.67.239.14.1545 USTANOWIONO

10.18 Uwagi dotyczące implementacji

Od samego początku TCP był zaprojektowany do współpracy ze sprzętem sieciowym różnych producentów. Specyfikacja TCP nie określa dokładnie, jak powinny działać wewnętrzne struktury implementacji. Te pytania pozostawia się programistom, aby znaleźć najlepsze mechanizmy dla każdej konkretnej implementacji.

Nawet RFC 1122 (dokument Wymagania hosta — wymagania gospodarza) pozostawia wystarczająco dużo miejsca na zmiany. Każda z zaimplementowanych funkcji jest oznaczona pewnym poziomem kompatybilności:

■ MAJ (dozwolone)

■ NIE WOLNO

Niestety czasami zdarzają się produkty, które nie realizują wymagań MUST. W rezultacie użytkownicy doświadczają niedogodności związanych z pogorszeniem wydajności.

Niektóre dobre praktyki wdrożeniowe nie są uwzględnione w standardach. Na przykład poprawa bezpieczeństwa jest możliwa poprzez ograniczenie wykorzystania dobrze znanych portów przez uprzywilejowane procesy systemowe, jeśli w lokalnym system operacyjny ta metoda jest obsługiwana. Aby zmaksymalizować wydajność, implementacje powinny mieć jak najmniej kopiowania i przenoszenia wysyłanych lub pobieranych danych.

Standardowy interfejs API nieokreślony(jak również polityka bezpieczeństwa), aby było wolne pole do eksperymentowania z różnymi zestawami narzędzia programowe... Może to jednak spowodować, że na każdej platformie będą używane różne interfejsy API i uniemożliwi przenoszenie oprogramowania aplikacji między platformami.

W rzeczywistości programiści opierają swoje zestawy narzędzi na interfejsie Socket API firmy Berkeley. Znaczenie interfejsu programistycznego wzrosło wraz z pojawieniem się WINSock (Windows Socket), co doprowadziło do szybkiego wzrostu liczby nowych aplikacji dla systemy stacjonarne który może działać na dowolnym interfejsie WINSock kompatybilnym ze stosem TCP / IP.

10.19 Dalsza lektura

Oryginalny standard TCP jest zdefiniowany w RFC 793. Aktualizacje, poprawki i wymagania dotyczące interoperacyjności są omówione w RFC 1122. Kern (Kash) i Partridge (Partridge) opublikowali artykuł Poprawa szacunków w obie strony w niezawodnych protokołach transportowych W magazynie Postępowanie ACM SIGCOMM 1987. Artykuł Jacobsona Unikanie i kontrola zatorów pojawił się w Materiały z warsztatów ACM SIGCOMM 1988. Jacobson wydał również kilka dokumentów RFC, które modyfikują algorytmy poprawy wydajności.

Podróżowanie przez protokoły sieciowe.

TCP i UDP to oba protokoły Warstwa transportowa... UDP to bezpołączeniowy protokół z niezabezpieczonym dostarczaniem pakietów. TCP (Transmission Control Protocol) to protokół zorientowany na połączenie z gwarantowanym dostarczaniem pakietów. Najpierw następuje uścisk dłoni (Hello. | Hello. | Porozmawiajmy? | No on.), Po czym połączenie jest uważane za ustanowione. Ponadto pakiety są przesyłane tam iz powrotem przez to połączenie (jest konwersacja) i sprawdzane jest, czy pakiet dotarł do odbiorcy. Jeśli pakiet został utracony lub dotarł, ale z bitową sumą kontrolną, jest wysyłany ponownie ("powtórz, nie słyszę"). Tak więc TCP jest bardziej niezawodny, ale jest bardziej skomplikowany z punktu widzenia implementacji i dlatego wymaga większego zegara/pamięci, co nie jest najmniej ważne dla mikrokontrolerów. Przykładami protokołów aplikacji korzystających z TCP są FTP, HTTP, SMTP i wiele innych.

TL; DR

HTTP (Hypertext Transfer Protocol) to protokół aplikacji, za pośrednictwem którego serwer wysyła strony do naszej przeglądarki. HTTP jest teraz wszechobecny w Sieć ogólnoświatowa informacje ze stron internetowych. Zdjęcie przedstawia lampkę na mikrokontrolerze z systemem operacyjnym na pokładzie, w którym kolory są ustawiane przez przeglądarkę.

Protokół HTTP jest tekstowy i dość prosty. Właściwie tak wygląda metoda GET, wysyłana przez narzędzie netcat na lokalny adres IPv6 serwera ze światłami:

~ $ nc fe80 :: 200: e2ff: fe58: b66b% mazko 80<

Metoda HTTP jest zwykle krótkim, pisanym wielką literą słowem angielskim, z uwzględnieniem wielkości liter. Każdy serwer musi obsługiwać co najmniej metody GET i HEAD. Oprócz metod GET i HEAD często stosowane są metody POST, PUT i DELETE. Metoda GET służy do żądania zawartości określonego zasobu, w naszym przypadku tutaj GET /b HTTP/1.0 gdzie ścieżka /b odpowiada za kolor (niebieski). Odpowiedź serwera:

HTTP / 1.0 200 OK Serwer: Contiki / 2.4 http://www.sics.se/contiki/ Połączenie: zamknij Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0 Content- typ: tekst / html Contiki RGB

Czerwony jest WYŁĄCZONY

Zielony jest wyłączony

Niebieski jest WŁĄCZONY

Kod statusu (mamy 200) jest częścią pierwszego wiersza odpowiedzi serwera. Jest to trzycyfrowa liczba całkowita. Pierwsza cyfra wskazuje klasę warunku. Po kodzie odpowiedzi zwykle następuje objaśniająca fraza w języku angielskim, oddzielona spacją, która wyjaśnia osobie powód tej konkretnej odpowiedzi. W naszym przypadku serwer działał bez błędów, wszystko w paczce (OK).

Zarówno żądanie, jak i odpowiedź zawierają nagłówki (każda linia to osobne pole nagłówka, para nazwa-wartość oddzielona jest dwukropkiem). Nagłówki kończą się pustą linią, po której mogą przejść dane.

Moja przeglądarka odmawia otwarcia lokalnego adresu IPv6, więc dodatkowy adres jest zapisany w oprogramowaniu mikrokontrolera, a ten sam prefiks musi być również przypisany do wirtualnego interfejsu sieciowego symulatora:

~ $ sudo ip addr add abcd :: 1/64 dev mazko # linux ~ $ netsh interface ipv6 set address mazko abcd :: 1 # windows ~ $ curl http://

Serwery, które implementują te protokoły w sieci firmowej, dostarczają klientowi adres IP, bramę, maskę sieci, serwery nazw, a nawet drukarkę. Użytkownicy nie muszą ręcznie konfigurować swoich hostów, aby korzystać z sieci.

System operacyjny QNX Neutrino implementuje inny protokół typu plug-and-play o nazwie AutoIP, który jest projektem komitetu autokonfiguracji IETF. Ten protokół jest używany w małych sieciach do przypisywania adresów IP hostom lokalnym. Protokół AutoIP niezależnie określa adres IP lokalny dla kanału, używając schematu negocjacji z innymi hostami i bez kontaktowania się z serwerem centralnym.

Korzystanie z protokołu PPPoE

PPPoE to skrót od Point-to-Point Protocol over Ethernet. Protokół ten hermetyzuje dane do transmisji przez mostowaną sieć Ethernet.

PPPoE to specyfikacja łączenia użytkowników sieci Ethernet z Internetem za pośrednictwem połączenia szerokopasmowego, takiego jak linia dzierżawiona, urządzenie bezprzewodowe lub modem kablowy. Wykorzystanie PPPoE i modemu szerokopasmowego zapewnia użytkownikom lokalnej sieci komputerowej indywidualny, uwierzytelniony dostęp do szybkich sieci danych.

PPPoE łączy Ethernet z PPP, aby efektywnie tworzyć oddzielne połączenie ze zdalnym serwerem dla każdego użytkownika. Kontrola dostępu, rozliczanie połączeń i wybór dostawcy usług zależą od użytkownika, a nie hosta. Zaletą tego podejścia jest to, że ani firma telefoniczna, ani dostawca usług internetowych nie muszą zapewniać w tym celu żadnego specjalnego wsparcia.

W przeciwieństwie do połączeń telefonicznych połączenia DSL i modemu kablowego są zawsze aktywne. Ponieważ fizyczne połączenie ze zdalnym dostawcą usług jest współużytkowane przez wielu użytkowników, potrzebna jest metoda rozliczania, która rejestruje nadawców i miejsca docelowe ruchu oraz obciąża użytkowników. PPPoE umożliwia użytkownikowi i zdalnemu hostowi uczestniczącemu w komunikacji wzajemne poznanie swoich adresów sieciowych podczas początkowej wymiany zwanej wykrycie(odkrycie). Po ustanowieniu sesji między indywidualnym użytkownikiem a witryną zdalną (taką jak dostawca usług internetowych), sesję można monitorować pod kątem narastania. W wielu domach, hotelach i korporacjach dostęp do Internetu jest współdzielony przez cyfrowe linie abonenckie z wykorzystaniem technologii Ethernet i PPPoE.

Połączenie PPPoE składa się z klienta i serwera. Klient i serwer pracują przy użyciu dowolnego interfejsu, który jest zbliżony do specyfikacji Ethernet. Ten interfejs jest używany do przydzielania adresów IP klientom, wiążąc te adresy IP z użytkownikami i opcjonalnie ze stacjami roboczymi, zamiast uwierzytelniania tylko stacji roboczej. Serwer PPPoE tworzy połączenie punkt-punkt dla każdego klienta.

Nawiązywanie sesji PPPoE

Aby utworzyć sesję PPPoE, należy skorzystać z usługipppoed... Modułio-pkt- * nZapewnia usługi protokołu PPPoE. Najpierw musisz biecio-pkt- *zodpowiedni sterownik... Przykład: