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.

rys2


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.

rys1

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:

Ponizszy rysunek przedstawia najprostszy scenariusz wymiany segmentow TCP przy zawieraniu i konczeniu polaczenia. Teraz omowimy szczegoly zawierania polaczenia. Aby ustanowic polaczenie TCP:

  1. 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".
  2. 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.
  3. 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).

rys3

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 tcp_connect()

Funkcja ta inicjuje aktywne polaczenie.
DEFINICJA: static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)

Funkcja tcp_accept()

Funkcja ta inicjuje pasywne polaczenie.
DEFINICJA: static struct sock *tcp_accept(struct sock *sk, int flags)

Funkcja tcp_sendmsg()

Funkcja ta wysyla dane z gniazda.
DEFINICJA: static int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int len, int nonblock, int flags)

Funkcja tcp_recvmsg()

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 tcp_close()

Funkcja ta zamyka polaczenie TCP.
DEFINICJA: static void tcp_close(struct sock *sk, unsigned long timeout)


Bibliografia

  1. Pliki zrodlowe Linuxa:
  2. W. Richard Stevens: TCP/IP Illustrated, Volume 1 - The Protocols
  3. RFC 793, Transmission Control Protocol
  4. Michael K. Johnson: Linux Kernel Hackers' Guide
  5. Krzysztof Mlynarski: Techniczna Strona Internetu, magazyn Software 3,4/96

Autor: Grzegorz Daniluk