Narzędzia użytkownika

Narzędzia witryny


sk2:sockets_full

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Poprzednia wersja
Nowa wersja
Poprzednia wersja
sk2:sockets_full [2017/11/21 15:08]
jkonczak [Serwer TCP]
sk2:sockets_full [2022/10/10 19:19] (aktualna)
jkonczak [Serwer TCP]
Linia 1: Linia 1:
 ====== Interface gniazd BSD (1/2) ====== ====== Interface gniazd BSD (1/2) ======
-Schemat kolejności wywołać funkcji bibliotecznych ​znajduje się na: \\ [[http://​www.cs.put.poznan.pl/​ddwornikowski/​sieci/​sieci2/​bsdsockets.html#​rys-1]]+Schemat kolejności wywołać funkcji bibliotecznych:​ \\ 
 +<​html><​object id="​svg-object"​ data="/​jkonczak/​_media/​sk2:​sockets.svg"​ type="​image/​svg+xml"></​object></​html>​\\ 
 +(Porównaj z: [[http://​www.cs.put.poznan.pl/​ddwornikowski/​sieci/​sieci2/​bsdsockets.html#​rys-1]].)
 ===== Serwer TCP ===== ===== Serwer TCP =====
-Aby oczekiwać na przychodzące połączenia TCP, po stworzeniu ​gniazda ​(''​socket(…)''​) wystarczy wywołać 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.\\ +Aby oczekiwać na przychodzące połączenia TCP konieczne jest stworzenie ​gniazda ​do odbierania nowych połączeń. Takie gniazdo, tzw. **gniazdo nasłuchujące** ​(listening), nie umożliwia odbierania ani wysyłania danych - **pozwala tylko na odbieranie przychodzących połączeń** i tworzy **dla każdego nowego połączenia kolejne gniazdo** reprezentujące to odebrane połączenie.
-Dlatego przed funkcją ''​listen(…)''​ używa się funkcji ''​bind(…)''​ do ustawienia lokalnego adresu gniazda. Funkcja ''​bind''​ przyjmuje jako argument strukturę ''​sockaddr''​.+
  
-Lokalny adres IP można ustawić na dowolny – **''​INADDR_ANY''​** lub wybrany przez siebie – np. 127.0.0.1 ​(''​INADDR_LOOPBACK''​) jeśli ​połączenia mają być ograniczone do localhosta.+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 adres gniazda**. Funkcja ''​bind''​ przyjmuje jako argument strukturę ''​sockaddr''​.
  
-Po wywołaniu funkcji ''​listen'' ​system operacyjny system operacyjny ​czeka na połączenia. ​Do odebrania nowego ​połączenia ​należyć funkcji ''​accept(…)''​. Funkcja accept ​zwróci ​nowe gniazdo reprezentujące nawiązane połączenie.+**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. \\ 
 +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ż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. 
 + 
 +<​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:
   * stworzy gniazdo,   * stworzy gniazdo,
-  * ustali adres (''​bind''​),​+  * ustali adres (''​bind''​), uwaga: sprawdzaj wynik funkcji ''​bind''​,
   * rozpocznie oczekiwanie na połączenia (''​listen''​),​   * rozpocznie oczekiwanie na połączenia (''​listen''​),​
     * ''​listen''​ jako drugi argument przyjmuje ile nowych połączeń może naraz czekać na odebranie funkcją accept     * ''​listen''​ jako drugi argument przyjmuje ile nowych połączeń może naraz czekać na odebranie funkcją accept
Linia 18: 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 28: 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 64: Linia 73:
 //Zadanie 6.// Odpowiedz na pytanie dlaczego DNS używa UDP zamiast TCP do zapytań. //Zadanie 6.// Odpowiedz na pytanie dlaczego DNS używa UDP zamiast TCP do zapytań.
  
-===== Klient ​UDP =====+===== UDP ===== 
 + 
 +Program korzystający z UDP musi stworzyć funkcją ''​socket''​ gniazdu typu ''​SOCK_DGRAM''​. 
 + 
 +Następnie program może (a jeśli ma pełnić rolę serwera, to powinien) wywołać funkcję ''​bind'',​ ustalając lokalny numer portu. 
 + 
 +Gniazdo UDP w każdym momencie po stworzeniu może wykonywać operacje odbioru i wysyłania danych – ''​sendto'',​ ''​recvfrom'',​ ''​recv'',​ ''​read''​. 
 + 
 +UDP jest bezpołączeniowe,​ więc nie da się na nim wykonać funkcji ''​shutdown''​. 
 +==== Klient UDP ====
  
 //Zadanie 7.// Napisz program, który korzystając z protokołu UDP wyśle dane (stały ciąg znaków) pod wskazany adres, następnie odbierze dane i się zakończy. //Zadanie 7.// Napisz program, który korzystając z protokołu UDP wyśle dane (stały ciąg znaków) pod wskazany adres, następnie odbierze dane i się zakończy.
  
-===== Serwer UDP =====+==== Serwer UDP ====
  
 //Zadanie 8.// Napisz program, który korzystając z protokołu UDP odbierze dane i odeśle je pod adres nadawcy zmieniając wielkość liter.\\ //Zadanie 8.// Napisz program, który korzystając z protokołu UDP odbierze dane i odeśle je pod adres nadawcy zmieniając wielkość liter.\\
sk2/sockets_full.1511273309.txt.gz · ostatnio zmienione: 2017/11/21 15:08 przez jkonczak