Do spisu tresci tematu 8
8.3.2 Transmission Control Protocol - TCP
Spis tresci
Wprowadzenie
TCP (ang. Transmission Control Protocol) jest protokolem warstwy transportu (ang. Transport Layer). Po przeczytaniu opisu protokolu IP wiadomo, ze IP nie zapewnia poprawnosci przesylania danych po sieci. W przypadku gdy modul IP zauwazy blad w datagramie, IP po prostu ignoruje ten datagram. Oczywiste jest, ze w wiekszosci zastosowan musi byc zagwarantowana poprawnosc przesylania danych. Wszystkie uslugi zwiazane z poprawnoscia przesylania zawarte sa w protokole TCP.
TCP zapewnia: bezpieczenstwo przesylu danych, polaczenia, przesyl strumieni bajtow. TCP pakuje dane uzytkownika w segmenty, ustawia budzik (ang. timeout) dla kazdych wysylanych danych, potwierdza odebrane dane, zapewnia kontrole przeplywu danych, oblicza i sprawdza sume kontrolna.
Protokol TCP jest uzywany w bardzo wielu znanych aplikacjach, takich jak: Telnet, Rlogin, FTP, HTTP i poczcie elektronicznej (SMTP).
Ponizszy rysunek przedstawia umiejscowienie protokolu TCP w modelu OSI i pozwala na lepsze zrozumienie dzialania sieci typu internet. Prosze zwrocic uwage na to, ze protokol TCP obslugiwany jest przez maszyny uzytkownikow (ang. host) a nie na poziomie urzadzen takich, jak router.
Naglowek TCP
Caly segment TCP (naglowek i dane ) zawarty jest w datagramie IP, tak jak to widac na ponizszym rysunku. Naglowek datagramu IP zawiera kilka informacji, miedzy innymi adresy hostow. Naglowek TCP znajduje sie za naglowkiem IP, i zawiera informacje specyficzne dla protokolu TCP. Podzial ten umozliwia istnienie innych protokolow niz protokol TCP na poziomie warstwy transportu w modelu OSI.
W pliku include/linux/tcp.h
zdefiniowany jest sam naglowek TCP. Normalnie ma on dlugosc 20 bajtow, ale tylko w przypadku braku dodatkowych opcji.
struct tcphdr {
__u16 source;
__u16 dest;
__u32 seq;
__u32 ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
res2:2;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
res2:2,
urg:1,
ack:1,
psh:1,
rst:1,
syn:1,
fin:1;
#else
#error "Adjust your defines"
#endif
__u16 window;
__u16 check;
__u16 urg_ptr;
};
Objasnienia poszczegolnych pol w strukturze tcphdr
.
source, dest
- Numery portow: zrodlowego i docelowego, aplikacji wysylajacej i odbierajacej. Te dwie wartosci razem z adresami IP: zrodlowym i docelowym, w naglowku IP, jednoznacznie okreslaja polaczenie (ang. connection).
seq
- Numer sekwencyjny (ang. sequence number) bajtu w strumieniu przesylanych danych, identyfikujacy pierwszy bajt danych w danym segmencie TCP. Jesli rozpatrzymy strumien bajtow przesylanych w jedna strone miedzy dwoma aplikacjami , okaze sie, ze modul TCP numeruje kazdy bajt numerem sekwencyjnym. Numer ten to 32 bitowa liczba bez znaku, cyklicznie zaokraglana do 0 po osiagnieciu 232 - 1.
ack_seq
- Poniewaz wszystkie przesylane bajty sa numerowane, ack_seq (ang. acknowledgment number) zawiera nastepny numer sekwencyjny bajtu, oczekiwanego przez nadawce ack_seq. Czyli ack_seq rowna sie numerowi sekwencyjnemu ostatniego poprawnie otrzymanego bajtu, dodac 1. Pole to wazne jest tylko gdy ustawiony jest bit ACK. Poniewaz dane w polaczeniu TCP moga byc przesylane w dwie strony, kazda ze stron polaczenia musi utrzymywac numery sekwencyjne dla danych przesylanych w kazdym z kierunkow.
doff
- Dlugosc naglowka TCP liczona w 32 bitowych slowach. Wbrew pozorom pole to jest potrzebne, poniewaz dlugosc opcji w naglowku TCP moze byc rozna.
res1, res2
- Bity zarezerwowane na przyszlosc. Musza byc ustawione na zero.
urg
- Gdy bit urg jest ustawiony, pole urg_ptr jest wazne.
ack
- Gdy bit urg jest ustawiony, pole ack_seq jest wazne.
psh
- Gdy bit psh jest ustawiony, modul odbiorczy TCP powinien przekazac dane aplikacji tak szybko, jak tylko jest to mozliwe.
rst
- Gdy bit rst jest ustawiony, oznacza to wyzerowanie (ang. reset) polaczenia.
syn
- Gdy bit syn jest ustawiony, oznacza to synchronizacje numerow sekwencyjnych przy inicjalizacji polaczenia.
fin
- Gdy bit fin jest ustawiony, oznacza to, ze nadawca skonczyl przesylac dane.
window
- Protokol TCP realizuje kontrole predkosci przeplywu danych wykorzystujac to pole. Mianowicie, pole to zawiera liczbe bajtow, poczynajac od bajtu okreslonego w polu ack_seq, ktore odbiorca jest w stanie odebrac.
check
- Suma kontrolna pokrywajaca naglowek i dane TCP. Suma ta, musi byc obliczona przez nadawce i sprawdzona przez odbiorce.
urg_ptr
- Pole to zawiera dodatnie przesuniecie (ang. offset), ktore musi byc dodane do numeru sekwencyjnego (
seq
), aby wyznaczyc numer sekwencyjny ostatniego bajtu pilnych danych (ang. ungent data). Wskaznik ten ma znaczenie tylko wtedy, gdy ustawiony jest bit URG. Ten rodzaj transmisji TCP jest wykorzystywany wtedy, gry nadawca chce przeslac odbiorcy dane "awaryjne".
Uslugi protokolu TCP
Przesyl danych
TCP potrafi przesylac strumienie danych w dwoch kierunkach miedzy dwoma uzytkownikami. Dane pakowane sa w segmenty, a nastepnie przesylane przez Internet. O tym czy dane sa wstrzymywane lub przekazywane do transmisji TCP decyduje sam.
Niezawodnosc
Protokol TCP uzywajac do przesylu danych przez Internet, protokolu IP, musi zabezpieczac sie przed zagubieniem, zduplikowaniem i znieksztalceniem segmentow.
Jest to osiagniete przez przypisanie segmentom "kolejnych numerow" i oczekiwaniu na pozytywne potwierdzenie odbioru danego segmentu przez odbiorce. Jednoczesnie przy wysylaniu segmentu ustawiany jest "budzik" (ang. timer) na okreslony czas. Jesli potwierdzenie odbioru nie nadchodzi, segment wysylany jest ponownie.
Odbiorca wykorzystuje "numeracje" segmentow do uporzadkowania segmentow ktore nadeszly w niewlasciwej kolejnosci, a takze do wyeliminowania zduplikowanych segmentow.
Do kazdego transmitowanego segmentu dodawana jest suma kontrolna, ktora jest sprawdzana u odbiory. W przypadku bledu, dany segment jest odrzucany i informacja o tym jest wysylana do nadajacego modulu TCP.
Kontrola przeplywu
Modul TCP otrzymujacy dane moze wplywac na ilosc danych wysylanych przez modul nadsylajacy. W przypadku zbyt szybkiego nadchodzenia danych moze to uchronic przed utrata czesci informacji na skutek niemoznosci obsluzenia ich przez zbytnio obciazony modul odbierajacy.
Protokol TCP dostarcza odbiorcy, mechanizmy do kontrolowania predkoscia przesylu danych. Jest to osiagniete przez odpowiedz odbiorcy zwana oknem (ang. window), wysylana do nadawcy danych. Rozmiar okna okresla liczba bajtow, ktore nadawca moze przeslac odbiorcy do czasu otrzymania nastepnego okna. Jesli liczba danych okreslona rozmiarem okna zostala nadana, to nadawca zmuszony jest przerwac nadawanie.
Wiele sesji transmisyjnych w jednym systemie
Aby zapewnic wielu procesom mozliwosc korzystania z TCP na jednym komputerze (ang. multiplexing), TCP korzysta ze zbioru portow. Porty w polaczeniu z adresami sieci i komputera w tej sieci (ang. host), definiuja gniazdo. Para gniazd jednoznacznie definiuje dane polaczenie. Gniazdo moze byc uzyte do wielokrotnych polaczen.
Przypisanie numeru portu do danego procesu jest obslugiwane niezaleznie na kazdym komputerze, to znaczy, ze numery portow po dwoch stronach polaczenia moga byc rozne.
Polaczenia
Bezpieczenstwo i kontrola przeplywu, opisane powyzej wymagaja aby TCP zainicjalizowal i utrzymywal pewne informacje o stanie przesylu danego strumienia danych. Te informacje w polaczeniu z gniazdami, numeracja segmentow i oknami (ang. window) sa zwane polaczeniem. Kiedy dwa procesy chca sie ze soba skomunikowac, ich moduly TCP musza zainicjowac polaczenie (zainicjowac informacje o stanie polaczenia). Po zakonczeniu komunikacji polaczenie jest zamykane, aby zwolnic zajmowane zasoby. Poniewaz polaczenie musi byc ustanowione miedzy dwoma niepewnymi komputerami w sieci (ang. host) i przeprowadzone z pomoca nie zapewniajacego bezpieczenstwa protokolu IP, wykorzystywany jest algorytm "trzykrotnego uscisku dloni" do nawiazania polaczenia.
Polaczenia
TCP jest protokolem polaczeniowym (ang. connection-oriented). Czyli, zanim dane zostana przeslane miedzy komputerami w sieci, musi byc ustanowione polaczenie miedzy nimi.
Protokol TCP dopuszcza stosowanie dwoch rodzajow polaczen z portami. Jest to zwiazane z dwoma rodzajami nawiazywania polaczen:
- Otwarcie pasywne (ang. passive open). Daje mozliwosc protokolowi warstwy aplikacji, poinformowania modulu TCP, iz nie chce on inicjowac polaczenia z wlasnej strony ale oczekuje na polaczenia przychodzace z zewnatrz. Linux otrzymujac tego typu zadanie, przypisuje procesowi numer portu, ktory bedzie wykorzystywany do oczekiwania na przychodzace polaczenia. W przypadku, gdy nadejdzie segment TCP zadajacy nawiazania polaczenia z tym wlasnie portem, system informuje o tym zdarzeniu proces przypisany do tego numeru portu. Nastepnie proces sam moze zadecydowac o akceptacji polaczenia. Wyrozniamy dwa typy otwarcia pasywnego:
- W pelni okreslone otwarcie pasywne (ang. fully specified passive open). Uzyty adres docelowy jest taki sam jak w otwarciu aktywnym. Czyli ten rodzaj otwarcia posiada w pelni okreslone gniazdo (ang. socket) identyfikujace drugi koniec polaczenia
- Nieokreslone otwarcie pasywne (ang. unspecified passive open). Czyli, z tym portem, polaczenie moze nawiazac dowolny proces. Gniazdo docelowe jest nieokreslone.
- Otwarcie aktywne (ang. active open). Ten rodzaj otwarcia polaczenia daje protokolowi wyzszej warstwy mozliwosc okreslenia gniazda docelowego, z ktorym aplikacja chce nawiazac polaczenie. Otwarcie aktywne jest najczesciej uzywane do zawarcia polaczenia z pasywnym gniazdem przypisanym innemu procesowi.
Ponizszy rysunek przedstawia najprostszy scenariusz wymiany segmentow TCP przy zawieraniu i konczeniu polaczenia. Teraz omowimy szczegoly zawierania polaczenia. Aby ustanowic polaczenie TCP:
- Klient (ang. client) wysyla SYN segment (segment inicjujacy polaczenie), z okreslonym numerem portu serwera, z ktorym chce sie polaczyc, dodatkowo klient przekazuje w tym segmencie, inicjujacy numer sekwencyjny (ang. ISN - initial sequence number). Na naszym rysunku ISM reprezentuje "J".
- Serwer odpowiada na wezwanie klienta wlasnym SYN segmentem, zawierajacym ISN serwera, czyli "K" na rysunku. Dodatkowo przesylane jest potwierdzenie SYN segmentu klienta, z wartoscia
ack
rowna "J+1". Bit SYN konsumuje jeden numer sekwencyjny.
- Klient musi potwierdzic (ang. acknowledge) SYN segment otrzymany od serwera. Aby to zrobic wysyla segment z polem
ack
rownym "K+1".
Algorytm ten nosi nazwe "trzykrotnego uscisku dloni" (ang. three-way handshake).
Jak sa wymieniane segmenty przy zamykaniu polaczenia, przedstawia rysunek powyzej. Kiedy do zawarcia polaczenia wystarcza wymiana trzech segmentow, to do zamkniecia polaczenia trzeba wymienic cztery segmenty. Jest to spowodowane tym, ze polaczenie TCP jest dwukierunkowe. Czyli dane moga byc przesylane w dwoch kierunkach. Wiec kazda strona polaczenia musi zamknac polaczenie (ang. shutdown) niezaleznie. Strona ktora pierwsza wyslala FIN segment (segment konczacy polaczenie) przeprowadza aktywne zamkniecie (ang. active close). Druga strona, ktora otrzymala FIN segment przeprowadza zamkniecie pasywne (ang. passive close).
Oczywiscie, roznych kombinacji zawierania i konczenia polaczen jest o wiele wiecej. Zainteresowanych odsylam do RFC 793.
Funkcje
Funkcja ta inicjuje aktywne polaczenie.
DEFINICJA: static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
Funkcja ta inicjuje pasywne polaczenie.
DEFINICJA: static struct sock *tcp_accept(struct sock *sk, int flags)
Funkcja ta wysyla dane z gniazda.
DEFINICJA: static int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int len, int nonblock, int flags)
Funkcja ta kopiuje dane ze struktury sock
do bufora uzytkownika.
DEFINICJA: static int tcp_recvmsg(struct sock *sk, struct msghdr *msg, int len, int nonblock, int flags, int *addr_len)
Funkcja ta zamyka polaczenie TCP.
DEFINICJA: static void tcp_close(struct sock *sk, unsigned long timeout)
Bibliografia
- Pliki zrodlowe Linuxa:
- W. Richard Stevens: TCP/IP Illustrated, Volume 1 - The Protocols
- RFC 793, Transmission Control Protocol
- Michael K. Johnson: Linux Kernel Hackers' Guide
- Krzysztof Mlynarski: Techniczna Strona Internetu, magazyn Software 3,4/96
Autor: Grzegorz Daniluk