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 [2024/10/07 20:25]
jkonczak
sk2:sockets_full [2025/10/16 22:26] (aktualna)
jkonczak
Linia 1: Linia 1:
 ====== Interface gniazd BSD (1/2) ====== ====== Interface gniazd BSD (1/2) ======
-Schemat kolejności wywołać funkcji bibliotecznych:​ \\+Schemat kolejności wywołań funkcji bibliotecznych:​ \\
 <​html><​object id="​svg-object"​ data="/​jkonczak/​_media/​sk2:​sockets.svg"​ type="​image/​svg+xml"></​object></​html>​\\ <​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]].)+----- 
 +Funkcja ''​socket''​ i kolejność wywoływania funkcji ​API gniazd na deskryptorze zwróconym przez tę funkcję:\\  
 +<​html><​object id="​svg-object"​ data="/jkonczak/_media/​sk2:​gniazdo-diagram.svg" type="​image/svg+xml"><​/object><​/html
 ===== Serwer TCP ===== ===== Serwer TCP =====
 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. 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.
Linia 15: Linia 18:
  
 **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''​)((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''​.)).+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 ​o wartości [[https://​elixir.bootlin.com/​linux/​v6.17.1/​source/​include/​linux/​socket.h#​L298|4096 ​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.
Linia 30: Linia 36:
   * zakończy program.   * zakończy program.
  
-~~Zadanie.#​~~a 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.#​2~~b Ustaw przed wywołaniem ''​bind''​ opcję ''​SO_REUSEADDR''​ gniazda (kod poniżej) i powtórz zadanie 2a.<code cpp>​const int one = 1;+~~Zadanie.#​~~a Krótko((https://​elixir.bootlin.com/linux/v6.17.1/​source/​include/​net/​tcp.h#​L128)) 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.#​2~~b 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>​
 <​small>​ <​small>​
Linia 42: Linia 48:
 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''​ ma 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 ​style="​user-select:​ none;"></​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);​
Linia 98: Linia 104:
  
 Tworząc gniazdo UDP należy użyć następujących argumentów:​ Tworząc gniazdo UDP należy użyć następujących argumentów:​
 +<​html><​div style=margin-top:​-1.2em></​div></​html>​
 <code cpp> <code cpp>
 socket(PF_INET,​ SOCK_DGRAM, IPPROTO_UDP) socket(PF_INET,​ SOCK_DGRAM, IPPROTO_UDP)
Linia 105: Linia 112:
 UDP nie nawiązuje połączenia – do odbioru i wysyłania wiadomości należy używać funkcji ''​sendto''​ i ''​recvfrom''​ (lub ''​recv''/''​read'',​ jeśli nie obchodzi nas nadawca). \\ W formie ułatwienia BSD socket API pozwala działać gniazdom UDP w trybie pseudo-połączeniowym - tzn. można wywołać funkcję ''​connect''​ (która ustali adres odbiorcy) i dalej korzystać z ''​send''​ / ''​write''​. UDP nie nawiązuje połączenia – do odbioru i wysyłania wiadomości należy używać funkcji ''​sendto''​ i ''​recvfrom''​ (lub ''​recv''/''​read'',​ jeśli nie obchodzi nas nadawca). \\ W formie ułatwienia BSD socket API pozwala działać gniazdom UDP w trybie pseudo-połączeniowym - tzn. można wywołać funkcję ''​connect''​ (która ustali adres odbiorcy) i dalej korzystać z ''​send''​ / ''​write''​.
  
-Przykład użycia funkcji ''​sendto''​ i ''​recvfrom'':​ <​html><​small></​html><​code cpp>+Przykład użycia funkcji ''​sendto''​ i ''​recvfrom'': ​ 
 +<​html><​div style=margin-top:​-1.2em></​div></​html>​ 
 +<​html><​small ​style="​user-select:​ none;"></​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);​
sk2/sockets_full.1728325520.txt.gz · ostatnio zmienione: 2024/10/07 20:25 przez jkonczak