Do spisu tresci tematu 9

9.1.5 Opcje gniazd




Spis tresci



Funkcje setsockopt() i getsockopt()

Za pomoca tych funkcji mozemy manipulowac zarowno opcjami dotyczacymi ogolnego programu obslugi gniazd, jak i poszczegolnych warstw protokolu w obrebie ktorego dziala gniazdo.

 DEFINCJE: int setsockopt (int sockfd, int level, int optname, char *optval, int optlen)
	   int getsockopt (int sockfd, int level, int optname, char *optval, int *optlen) 
    WYNIK:  0 w przypadku powodzenia
           -1 gdy blad: 
	         errno = EBADF       (argument sockfd nie jest poprawnym deskryptorem)
	                 ENOTSOCK    (sockfd nie jest deskryptorem gniazda)
			 ENOPROTOOPT (nieprawidlowa opcja na wskazanym poziomie)
		         EFAULT      (optval wskazuje na nieprawidlowy adres) 
				
Znaczenie argumentow jest nastepujace:

sockfd - deskryptor gniazda, level - poziom, ktorego dotyczy opcja, mozliwe wartosci: SOL_SOCKET - nawyzszy poziom - ogolny program obslugi gniazd, IPPROTO_xxx - opcje protokolow,

optval - wskaznik zmiennej uzytkownika, z ktorej pobierana jest wartosc ustanawianej opcji (setsockopt) lub na ktora zapisuje sie wartosc wybranej opcji (getsockopt),

optlen - rozmiar zmiennej wskazywanej przez optval.


Implementacja


Struktura sock posiada szereg pol o nazwach zblizonych do nazw odpowiednich opcji, wiekszosc z nich to pola znacznikowe. Przy tworzeniu gniazda pola te sa inicjalizowane domyslnymi wartosciami, zas zmiany ich wartosci dokonuja funkcje: (plik net/core/sock.c)
int sock_setsockopt(struct sock *sk, int level, int optname,
		    char *optval, int optlen);
oraz
int sock_getsockopt(struct sock *sk, int level, int optname,
		    char *optval, int *optlen);


Wykaz wazniejszych opcji

Ponizej wymienione sa wazniejsze opcje ustawiane za pomoca funkcji set[get]sockopt()

UWAGA: Przy opcjach - znacznikach przyjeta nastepujaca konwencja: (optval != 0) oznacza "tak" , (optval == 0) oznacza "nie". Przy opcjch, ktorych nie mozna ustawiac (a tylko sprawdzac ich wartosci) widnieje napis ,,(tylko get)''.

Poziom interfejsu gniazd (level = SOL_SOCKET)

  • SO_BROADCAST

    Zezwala / zabrania rozglaszania komunikatow. Mozliwe tylko w sieciach udostepniajacych mozliwosc rozglaszania (jadro nie udostepnia programowej symulacji tego mechanizmu !) i tylko w przypadku gniazd datagramowych.

  • SO_DEBUG

    Wlacza / wylacza diagnostyke prowadzona na nizszych warstwach protokolow (polega ona na utrzymywaniu przez jadro historii ostatnio wyslanych i odebranych pakietow).

  • SO_DONTROUTE

    Ustala, czy wysylane komunikaty moga omijac normalne mechanizmy wyboru trasy stosowane przez dany protokol.

  • SO_ERROR

    (tylko get) Zwraca i zeruje status bledu dla gniazda.

  • SO_TYPE

    (tylko get) Zwraca rodzaj gniazda. Mozliwosc sprawdzenia typu gniazda moze byc pozyteczna np. dla procesu, ktory dziedziczy deskryptor gniazda.

  • SO_KEEPALIVE

    (tylko dla gniazd typu SOCK_STREAM) Umozliwia badanie stanu polaczenia za pomoca okresowych transmisji przez polaczone gniazdo. Jezeli druga strona polaczenia nie odpowiada na te komunikaty, to polaczenie uwaza sie za zerwane, zas procesy uzywajace gniazda otrzymuja sygnal SIGPIPE przy probie wyslania danych, a wartosc errno jest ustawiana na ETIMEDOUT.

  • SO_LINGER

    (tylko dla gniazda typu SOCK_STREAM) Okresla jakie czynnosci maja byc wykonywane w momencie wywolania funkcji close, gdy pozostaly komunikaty czekajace na wyslanie. Domyslnie funkcja close wykonuje natychmiastowy powrot, a system probuje wyslac te dane. Ustawienie opcji SO_LINGER wymaga przeslania do jadra (w zmiennej optval) nastepujacej struktury (zdefiniowanej w pliku include/linux/socket.h:

                     struct linger {
                        int l_onoff;   /* Flaga logiczna: 0  = wlacz, 
                                                          !0 = wylacz */
                        int l_linger;  /* Czas zwlekania (w sekundach)     */
    		 }
    
    Czas zwlekania rowny zero oznacza, ze przy zamknieciu gniazda jadro ma zignorowac niewyslane dane.

  • SO_DONTLINGER

    Wylaczenie opcji linger.

  • SO_RCVBUF, SO_SNDBUF

    Okreslenie rozmiarow buforow dla kolejek danych pobieranych i wysylanych. Ograniczenia na wielkosc tych buforow w Linuxie: co najmniej 256 i co najwyzej 65536 bajtow Domyslny rozmiar obu buforow okreslaja stale odpowiednio: SK_RMEM_MAX oraz SK_WMEM_MAX, ktore w zaleznosci od ustawienia flagi CONFIG_SKB_LARGE przy kompilacji jadra maja jednakowe wartosci: 65536 lub 32767 bajty.

  • SO_REUSEADDR

    Ustawienie tej opcji zezwala na ponowne wykorzystanie tego samego numeru portu przez gniazdo bez koniecznosci odczekiwania czasu okreslonego stala TCP_TIMEWAIT_LEN. Przy obecnosci tej opcji nadal gniazdo zamkniete instrukcja close() jest zachowywane w strukturach jadra w stanie TIME_WAIT, ale dozwolone jest jego usuniecie przez przypisanie innemu gniazdu tego samego numeru portu. Wiecej szczegolow - w opisie funkcji bind()

  • SO_OOBINLINE

    Oznacza, ze dane wysokopriorytetowe maja byc umieszczane w normalnej kolejce danych wejsciowych. Wowczas nie jest wymagany znacznik MSG_OOB w funkcjach pobierania danych.

    Poziom protokolow

    (level = IPPROTO_TCP)

  • TCP_MAXSEG

    (tylko get) Sprawdzenie maksymalnego rozmiaru segmentu, jakiego moze uzyc gniazdo.

  • TCP_NODELAY

    Ustawienie tej opcji wylacza grupowanie pakietow wysylanych przez warstwe TCP (Nagle buffering algorithm). Przydatne jedynie gdy wysylamy czesto male ilosci danych bez potrzeby natychmiastowego potwierdzenia kazdego komunikatu (np. wysylanie przez klienta informacji za posrednictwem myszki z terminala ,,okienkowego'').

    (level = IPPROTO_IP)

  • IP_OPTIONS

    Pozwala ustalic / odczytac opcje w naglowku IP komunikatow wysylanych przez gniazdo. Opcje te zapisane sa w parametrze optval. Mozliwosc ta wymaga znajomosci budowy naglowka IP (patrz: Temat 8, rozdzialy o IP).


    Inne sposoby konfigurowania gniazd

    Oprocz omowionych powyzej funkcji setsockopt() i getsockopet(), specjalnie zaprojektowanych do manipulowania opcjami, konfigurowac gniazda mozna przy pomocy dobrze znanych ,,plikowych'' funkcji ioctl() oraz fcntl():
    Opis ich implementacji znajduje sie w rozdziale 9.1.9

    int ioctl(int fd, unsigned long request, char *arg);
    

    Wazniejsze operacje dotyczace gniazd (wartosc argumentu request):

    SIOCSPGRP, FIOSETOWN, SIOCGPGRP, FIOGETOWN - patrz tutaj

    SIOCATMARK - przekazuje (jako wartosc *arg) liczbe rozna od zera, gdy w strumieniu danych wejsciowych znajduja sie dane wysokopriorytetowe.

    W tym miejscu warto zaznaczyc, iz funkcja ioctl() pozwala rowniez na ustalenie wielu parametrow dotyczacych konkretnych interfejsow sieciowych. Ich omawianie nie jest jednakze tematem niniejszego opracowania.

    int fcntl(int fd, int cmd, int arg);
    
    FNDELAY - ustanawia operacje wejscia/wyjscia na gniazdku nieblokujacymi - wowczas funkcje ktore zazwyczaj dzialaja blokujaco, beda wykonywac natychmiastowy powrot i ustawiac wartosc errno na EWOULDBLOCK (wyjatek: connect() - EINPROGRESS).

    F_SETOWN, F_GETOWN, FASYNC - patrz tutaj


    Bibliografia

    1. Pliki zrodlowe Linuxa:
    2. W. Richard Stevens: "Programowanie zastosowan sieciowych w systemie Unix"
    3. M. Gabassi, B. Dupouy: "Przetwarzanie rozproszone w systemie UNIX"
    4. Dokumentacja Linuxa 2.0.0 - strony man oraz pliki info
    5. Vic Metcalfe, Andrew Gierth: "Programming sockets in C - FAQ"


    Autor: Piotr Walczuk