[ Pobierz całość w formacie PDF ]
.1.2), tylkopozostaje w niej, zmieniajac jedynie swoj stan na TCP_TIME_WAIT.Podczas przesylania danych zdarza sie bowiem, ze przesylany komunikatzostanie uznany za zaginiony, a w rzeczywistosci bedzieprzetrzymywany przez jakis router pomiedzy stacja zrodlowa a docelowa.Przed wyslaniem komunikatu w dalsza droge polaczenie moze zostaczamkniete przez strone oczekujaca na ,,zaginiony'' pakiet.Jesli natychmiast zostanie stworzone gniazdona tym samym porcie, co przed chwila zamkniete,to moze sie zdarzyc, ze zawieruszony komunikat dotrze donowego gniazda.Dlatego tez standartowo po stronie zamykajacej polaczeniegniazdo pozostaje w stanie TCP_TIME_WAIT przez czas okreslony stala(zdefiniowana w pliku: include/net/tcp.h)#define TCP_TIMEWAIT_LEN (60*Hz) /* Czyli 60 sek.*/(w innych systemach od 20 sek.do 4 min.) W czasie pobytu gniazda w stanieTCP_TIME_WAIT ignorowane sa nadchodzace komunikaty.Istnieje jednak mozliwosc wymuszenia przydzielania gniazdu numeruzablokownego portu, opisana w rozdziale 9.1.5 o opcjach gniazd (opcja SO_REUSEADDR).Uzywanie tejopcji moze byc jednak niebezpieczne - narazamy sie na otrzymanie smieci z powodowopisanych powyzej.Wywolanie funkcji bind() jest obowiazkowe dla procesu - serwera.Klient zreguly nie musi bezposrednio wywolywac bind() - proba nawiazania polaczenia(connect()) w protokole bezpolaczeniowym badz wyslania danych automatycznie przypiszegniazdu klienta efemeryczny numer portu i dostarczy go serwerowi.Automatyczne odszukaniewolnego numeru portu wykonuje (dla gniazda Internetowego)funkcja int inet_autobind(struct sock* sk);Funkcja ta nie robi nic, jesli gniazdo ma juz przydzielony numer portu.Wprzeciwnym przypadku szuka wolnego numeru portu przegladjac zbior wszystkichgniazd umieszczonych w tablicy haszujacej sock_array[].Dziedzina Unixa (plik:net/unix/af_unix.c)static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen){if (nazwa gniazda != NULL || zla wartosc addrlen)return -EINVAL;zakoncz NULL'em podana nazwe sciezki;if(przydzielony i-wezel w filesystemie dla gniazda)return -EINVAL; /* Mamy juz przydzielona nazwe */zapisz nazwe sciezki w polu protinfo.af_unix.name struktury sock;utworz plik specjalny o podanej nazwie; /* funkcja mknod */znajdz odpowiadajacy mu i-wezel; /* funkcja namei */umiesc wskaznik na utworzony i-wezel w polu protinfo.af_unix.inode;return 0;}UWAGA:W dziedzinie Unixa mozliwosc automatycznego nazywania gniazda nie istnieje,gdyz gniazda identyfikowane sa nazwami sciezek.Zlecenie jadruautomatycznego tworzenia nazwy dla gniazda mogloby spowodowac efekty uboczne (np.proba tworzeniapliku w katalogu bez praw dostepu lub niejednoznacznosc nazw).Pobieranie nazw gniazdFunkcja getsockname()Przekazuje nazwe zwiazana z gniazdem poprzez asocjacje.Dzieki niej moznapoznac numer portu automatycznie przydzielony prez system.DEFINICJA: int getsockname(int fd, struct sockaddr *sockaddr, int *sockaddrlen)WYNIK: 0 w przypadku sukcesu-1 gdy blad: errno = EBADF (fd nie jest deskkryptorem)ENOTSOCK (deskryptor fd nie wskazuje na gniazdo)Adres zwiazany z gniazdem jest zapisywany pod adresempamieci przekazanym jako sockaddr (musi byc uprzedniozaalokowane miejsce!).Pod adresemsockaddrlen zapisana zostaje wielkosc struktury przechowujacejadres.Implementacja:Jest oczywista.Dzialanie funkcji sprowadza sie do zwroceniadanych zapisanych w polach strukturysock:W dziedzinie Internetu adres przechowywany jest w polach rcv_addr isaddr (moze go tam nie byc jesli gniazdo jest dopiero costworzone, wtedy pobierany jest adres komputera z warstwy IP).Numer portuzapisany jest w polu dummy_th.source.W dziedzinie Unixa lancuch bedacy nazwa gniazda pamietany jest w poluprotoinfo.af_unix.name struktury sock.Funkcja getpeername()Zwraca nazwe gniazda procesu partnera, ktory jest polaczony z danym gniazdem.DEFINICJA: int getpeername(int fd, struct sockaddr *peeraddr, int *peeraddrlen)WYNIK: 0 w przypadku sukcesu-1 gdy blad: errno = EBADF (fd nie jest deskkryptorem)ENOTSOCK (deskryptor fd nie wskazuje na gniazdo)ENOTCONN (brak polaczenia)Analogicznie jak w funkcji getsockname() parametrfd oznacza deskryptor gniazda, zas peeraddr ipeeraddrlen - adresy pod ktorymi beda zapisane: adres partnerai dlugosc adresu.Implementacja:Dzialanie funkcji sprowadza sie do sprawdzenia, czy gniazdo jest w stanie polaczenia,(jesli nie - sygnalizowany jest blad: ENOTCONN), a nastepniezwrocenia wartosci przechowywanych w strukturzesockW dziedzinie Internetu numer portu procesu odleglego przechowywanyjest w polu dummy_th.dest,zas jego adres w polu daddr.(Wartosci tych pol sa ustawianepodczas nawiazywania polaczen).W dziedzinie Unixa pobieramy nazwe gniazdka partnera odwolujac sie doniego bezposrednio (pole protinfo.af_unix.other strukturysock wskazuje na gniazdo, z ktorym jestesmy polaczeni).BibliografiaPliki zrodlowe Linuxa:include/linux/net.h(struktury: socket, proto_ops oraz definicje stalych)include/net/sock.h(definicje struktur sock i proto)net/socket.h (definicja struktury sockaddr)net/socket.c (implementacja funkcji systemowych - najwyzszy poziom)net/ipv4/af_inet.c (implementacja funkcji systemowych - dziedzina Internetu)net/unix/af_unix.c (implementacja funkcji systemowych - dziedzina Unixa)W.Richard Stevens: "Programowaniezastosowan sieciowych w systemie Unix"M.Gabassi, B.Dupouy: "Przetwarzanie rozproszone w systemie UNIX"Dokumentacja Linuxa 2.0 - strony man oraz pliki infoVic Metcalfe, Andrew Gierth: "Programming sockets in C - FAQ"Autor: Piotr Walczuk
[ Pobierz całość w formacie PDF ]