Różnice między wybraną wersją a wersją aktualną.
Both sides previous revision Poprzednia wersja Nowa wersja | Poprzednia wersja | ||
sk2:sockets_full [2019/10/14 21:00] jkonczak [Interface gniazd BSD (1/2)] |
sk2:sockets_full [2022/10/10 19:19] (aktualna) jkonczak [Serwer TCP] |
||
---|---|---|---|
Linia 7: | Linia 7: | ||
Gniazdo nasłuchujące tworzy się wywołując po stworzeniu gniazda (''socket(…)'') funkcję ''listen(…)'', ale: jeśli wcześniej nie ustawi się adresu gniazda, system operacyjny wylosuje efemeryczny port i rozpocznie nasłuch na dowolnym adresie IP na tym porcie.\\ | Gniazdo nasłuchujące tworzy się wywołując po stworzeniu gniazda (''socket(…)'') funkcję ''listen(…)'', ale: jeśli wcześniej nie ustawi się adresu gniazda, system operacyjny wylosuje efemeryczny port i rozpocznie nasłuch na dowolnym adresie IP na tym porcie.\\ | ||
- | Dlatego przed funkcją ''listen(…)'' **należy funkcją ''bind(…)'' ustawić lokalny adresu gniazda**. Funkcja ''bind'' przyjmuje jako argument strukturę ''sockaddr''. | + | Dlatego przed funkcją ''listen(…)'' **należy funkcją ''bind(…)'' ustawić lokalny adres gniazda**. Funkcja ''bind'' przyjmuje jako argument strukturę ''sockaddr''. |
**Lokalny adres IP nasłuchującego gniazda zwykle ustawia się na ustawić na dowolny – ''INADDR_ANY''**. Inny lokalny adres IP ustawia się, jeśli gniazdo ma odbierać połączenia kierowane tylko na ten adres – np. 127.0.0.1 (''INADDR_LOOPBACK'') jeśli połączenia mają być ograniczone do połączeń z localhosta. | **Lokalny adres IP nasłuchującego gniazda zwykle ustawia się na ustawić na dowolny – ''INADDR_ANY''**. Inny lokalny adres IP ustawia się, jeśli gniazdo ma odbierać połączenia kierowane tylko na ten adres – np. 127.0.0.1 (''INADDR_LOOPBACK'') jeśli połączenia mają być ograniczone do połączeń z localhosta. | ||
**Wywołanie funkcji ''listen'' nakazuje systemowi operacyjnemu czekać na połączenia** (porównaj z: ''connect''). Wykonanie funkcji listen jest natychmiastowe – ta funkcja nie czeka na połączenie, tylko informuje system operacyjny że nowe połączenia przychodzące na ustawiony adres mają być kierowane na to gniazdo. \\ | **Wywołanie funkcji ''listen'' nakazuje systemowi operacyjnemu czekać na połączenia** (porównaj z: ''connect''). Wykonanie funkcji listen jest natychmiastowe – ta funkcja nie czeka na połączenie, tylko informuje system operacyjny że nowe połączenia przychodzące na ustawiony adres mają być kierowane na to gniazdo. \\ | ||
- | Argumentem funkcji ''listen'' jest ilość nowych połączeń które czekają w kolejce na odebranie (tj. połączeń dla których nie wykonano jeszcze funkcji ''accept''). | + | Argumentem funkcji ''listen'' jest ilość nowych połączeń które czekają w kolejce na odebranie (tj. połączeń dla których nie wykonano jeszcze funkcji ''accept'')((Argument "backlog" funkcji ''listen'' powinien się zawierać w zakresie ''1''÷''SOMAXCONN'' (w tej chwili równe 128 w Linuksie) i jest traktowany jako podpowiedź, tzn. system operacyjny może używać innego limitu niż podany w argumencie ''listen''.)). |
Do odebrania nowych połączeń używa się funkcji ''accept(…)''. **Funkcja ''accept'' zwraca nowe gniazdo** reprezentujące nawiązane połączenie. | Do odebrania nowych połączeń używa się funkcji ''accept(…)''. **Funkcja ''accept'' zwraca nowe gniazdo** reprezentujące nawiązane połączenie. | ||
+ | |||
+ | <html><small></html>Tworzenie kolejnych deskryptorów plików oraz wyniki ''lsof'', ''strace'' i ''ss'' są zaprezentowane [[sk2:sockets_full:tcp_srv_img|tutaj]]<html></small></html> | ||
//Zadanie 1:// Napisz program, który: | //Zadanie 1:// Napisz program, który: | ||
Linia 25: | Linia 27: | ||
* zakończy program. | * zakończy program. | ||
- | //Zadanie 2a:// Krótko((https://github.com/torvalds/linux/search?q=TCP_TIMEWAIT_LEN)) po zamknięciu programu serwera sprawdź poleceniem ''netstat -tpn'' w jakim stanie jest połączenie. Przypomnij sobie co oznacza ten stan - [[https://tools.ietf.org/html/rfc793#page-22|RFC793]]. Spróbuj w tym czasie uruchomić ponownie program serwera. \\ //Zadanie 2b:// Ustaw przed wywołaniem ''bind'' opcję ''SO_REUSEADDR'' gniazda (kod poniżej) i powtórz zadanie 2a.<code cpp>const int one = 1; | + | //Zadanie 2a:// Krótko((https://github.com/torvalds/linux/search?q=TCP_TIMEWAIT_LEN)) po zamknięciu programu serwera sprawdź poleceniem ''netstat -tpn'' oraz ''ss -atnop'' w jakim stanie jest połączenie. Przypomnij sobie co oznacza ten stan - [[https://tools.ietf.org/html/rfc793#page-22|RFC793]]. Spróbuj w tym czasie uruchomić ponownie program serwera. \\ //Zadanie 2b:// Ustaw przed wywołaniem ''bind'' opcję ''SO_REUSEADDR'' gniazda (kod poniżej) i powtórz zadanie 2a.<code cpp>const int one = 1; |
setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));</code> | setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));</code> | ||
Linia 35: | Linia 37: | ||
Funkcja ''accept'' (podobnie jak wprowadzana za chwilę ''recvfrom'') może przekazać informację o adresie z którego nawiązano połączenie. W tym celu należy jej podać: | Funkcja ''accept'' (podobnie jak wprowadzana za chwilę ''recvfrom'') może przekazać informację o adresie z którego nawiązano połączenie. W tym celu należy jej podać: | ||
* gdzie ma zapisać ten adres – tj. podać adres struktury sockaddr (drugi argument) | * gdzie ma zapisać ten adres – tj. podać adres struktury sockaddr (drugi argument) | ||
- | * adres zmiennej, która w momencie wywołania ''accept'' na wpisany rozmiar przekazanej struktury (trzeci argument)<html><small></html><code cpp> | + | * adres zmiennej, która w momencie wywołania ''accept'' ma wpisany rozmiar przekazanej struktury (trzeci argument)<html><small></html><code cpp> |
sockaddr_in nazwa_zmiennej; | sockaddr_in nazwa_zmiennej; | ||
socklen_t inna_zmienna = sizeof(nazwa_zmiennej); | socklen_t inna_zmienna = sizeof(nazwa_zmiennej); | ||
- | client = accept(ssock, &nazwa_zmiennej, &inna_zmienna); | + | client = accept(ssock, (sockaddr*)&nаzwa_zmiennej, &innа_zmienna); |
</code><html></small></html> | </code><html></small></html> | ||
Jeśli drugi i trzeci argument są niezerowe, ''accept'' wypisuje przekazaną strukturę (drugi argument) i ustawia ile bajtów przekazanej struktury wypełnił (trzeci argument). | Jeśli drugi i trzeci argument są niezerowe, ''accept'' wypisuje przekazaną strukturę (drugi argument) i ustawia ile bajtów przekazanej struktury wypełnił (trzeci argument). | ||
Linia 80: | Linia 82: | ||
UDP jest bezpołączeniowe, więc nie da się na nim wykonać funkcji ''shutdown''. | UDP jest bezpołączeniowe, więc nie da się na nim wykonać funkcji ''shutdown''. | ||
- | |||
==== Klient UDP ==== | ==== Klient UDP ==== | ||