Narzędzia użytkownika

Narzędzia witryny


sk2:sockets_netdbs

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_netdbs [2019/10/21 14:36]
jkonczak [getaddrinfo]
sk2:sockets_netdbs [2023/10/17 14:03] (aktualna)
jkonczak
Linia 10: Linia 10:
 #include <​arpa/​inet.h>​ #include <​arpa/​inet.h>​
 #include <​netdb.h>​ #include <​netdb.h>​
 +#include <​cstdio>​
  
 int main() { int main() {
     ​     ​
-    std::thread t1([&]{+    std::thread t1([]{
         sleep(1);         sleep(1);
         gethostbyname("​spam.org"​);​         gethostbyname("​spam.org"​);​
     });     });
     ​     ​
-    std::thread t2([&]{ +    std::thread t2([]{ 
-        hostent* ret = gethostbyname("​fc.put.poznan.pl"​);​+        hostent* ret = gethostbyname("​cat.put.poznan.pl"​);​
         sleep(2);         sleep(2);
         printf("​%s:​ %s\n", ret->​h_name,​ inet_ntoa(**(in_addr**)ret->​h_addr_list));​         printf("​%s:​ %s\n", ret->​h_name,​ inet_ntoa(**(in_addr**)ret->​h_addr_list));​
Linia 36: Linia 37:
 <​html><​small></​html>​ <​html><​small></​html>​
 Kompilator GCC udostępnia wiele rozszerzeń "​łatających"​ braki standardów [[https://​gcc.gnu.org/​onlinedocs/​gcc/​C-Extensions.html]].\\ Kompilator GCC udostępnia wiele rozszerzeń "​łatających"​ braki standardów [[https://​gcc.gnu.org/​onlinedocs/​gcc/​C-Extensions.html]].\\
-Między innymi ​wprowadza funkcje ​''​gethostbyname_r''​ (funkcje ''​*_r''​ są reentrant, tj. można je bezpiecznie ​stosować w aplikacjach wielowątkowych [[https://​en.wikipedia.org/​wiki/​Reentrancy_%28computing%29]]) ​+Towarzysząca mu biblioteka [[https://​www.gnu.org/​software/​libc/​|glibc]] wprowadza między innymi ​funkcję ​''​[[https://​www.gnu.org/​software/​libc/​manual/​html_node/​Host-Names.html#​index-gethostbyname_005fr|gethostbyname_r]]''​ (funkcje ''​*_r''​ są reentrant, tj. można je łatwiej ​stosować w aplikacjach wielowątkowych [[https://​en.wikipedia.org/​wiki/​Reentrancy_%28computing%29]]). ''​gethostbyname_r''​ może być używana współbieżnie.
  
 <code cpp> <code cpp>
 hostent he, *resptr; hostent he, *resptr;
- int status, retval; +int status, retval; 
- char buffer[4096];​ +char buffer[4096];​ 
- retval = gethostbyname_r("​fc.put.poznan.pl",​ &he, buffer, sizeof(buffer),​ &​resptr,​ &​status);​ +retval = gethostbyname_r("​cat.put.poznan.pl",​ &he, buffer, sizeof(buffer),​ &​resptr,​ &​status);​ 
- if(retval) +if(retval) 
- error(1,​0,"​gethostbyname_r error: %s", hstrerror(status));​ +    error(1,​0,"​gethostbyname_r error: %s", hstrerror(status));​ 
- if(!resptr) +if(!resptr) 
- error(1,​0,"​empty result"​);​ +    error(1,​0,"​empty result"​);​ 
- print(resptr);​ +print(resptr);</​code>​
-</​code>​+
 <​html></​small></​html>​ <​html></​small></​html>​
  
 ===== getaddrinfo ===== ===== getaddrinfo =====
-Standard POSIX wprowadza funkcje ''​getaddrinfo'',​ która pozwala na bezpieczne tłumaczenie nazwy domenowej na  adresy IP (zarówno IPv4 i IPv6). Funkcja od razu tworzy gotową strukturę ''​sockaddr''​. Wynik musi być zwolniony przez programistę funkcją ''​freeaddrinfo''​.+Standard POSIX wprowadza funkcje ''​getaddrinfo'',​ która pozwala na bezpieczne tłumaczenie nazwy domenowej na  adresy IP (zarówno IPv4 i IPv6). Funkcja od razu tworzy gotową strukturę ''​sockaddr''​. Wynik musi być zwolniony przez programistę funkcją ''​freeaddrinfo''​. Poza ''​getaddrinfo''​ standard wprowadza też m. inn. funkcję do tłumaczenia ''​sockaddr*''​ na tekst – ''​getnameinfo''​.
  
 <​html><​small></​html>​ <​html><​small></​html>​
 Składnia: <code cpp> Składnia: <code cpp>
-int getaddrinfo( ​                 // zwraca 0 (ok) lub -1 (błąd+int getaddrinfo( ​                 // zwraca 0 (ok) lub niezerowy kod ędu (można go przerobić na tekst używając gai_strerror)
     const char * ip_or_hostname, ​ // nazwa domenowa lub adres IP      const char * ip_or_hostname, ​ // nazwa domenowa lub adres IP 
-    const char * port_or_service,​ // numer portu (np. "​80"​ lub nazwa usługi (np. "​http",​ ustawi port na 80)+    const char * port_or_service,​ // numer portu (np. "​80"​lub nazwa usługi (np. "​http",​ ustawi port na 80)
     const struct addrinfo *hints, // pozwala wybrać typ adresu, wyłączyć używanie DNS, etc.     const struct addrinfo *hints, // pozwala wybrać typ adresu, wyłączyć używanie DNS, etc.
     struct addrinfo **res); ​      // pole na wynik (jeśli puste - nic nie znaleziono)     struct addrinfo **res); ​      // pole na wynik (jeśli puste - nic nie znaleziono)
-</​code>​<​html></​small></​html>​Opis struktury ''​addrinfo''​ znajdziesz na stronie manuala do getaddringo (''​man getaddrinfo''​).+</​code>​
  
 +Definicja struktury ''​addrinfo'':<​code cpp>
 +struct addrinfo {
 +    int ai_flags;
 +    int ai_family; ​   // ai_family, ai_socktype i ai_protocol mają znaczenie identyczne jak
 +    int ai_socktype; ​ // w funkcji socket(). Mogą być ustawione w podpowiedziach na wybraną
 +    int ai_protocol; ​ // wartość lub na 0 (wtedy oznaczają wszystkie pasujące wartości)
 +    socklen_t ai_addrlen; ​         // ai_addr to adres o długości ai_addrlen który może być
 +    struct sockaddr *ai_addr; ​     // użyty w funkcji connect lub bind
 +    char *ai_canonname;​
 +    struct addrinfo *ai_next; ​ // struktura addrinfo tworzy jednokierunkową linked listę, ai_next wskazuje na jej następny element ​
 +};</​code><​html></​small></​html>​
 +
 +Pełen opis funkcji ''​getaddrinfo''​ i struktury ''​addrinfo''​ znajdziesz na stronie manuala do getaddrinfo (''​man getaddrinfo''​) <​html><​small></​html>​ lub w standardzie POSIX ([[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​freeaddrinfo.html|[1]]],​ [[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​getnameinfo.html|[2]]],​ [[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​gai_strerror.html|[3]]])<​html></​small></​html>​.
 +\\
 +Uwaga: ''​getaddrinfo''​ w razie sukcesu zwraca ''​0'',​ a w przypadku błędu zwraca jego kod.
  
 Przykłady użycia: Przykłady użycia:
Linia 68: Linia 83:
 #include <​netdb.h>​ #include <​netdb.h>​
 #include <​cstdio>​ #include <​cstdio>​
-#include <​error.h>​+#include <​error.h> ​ // niestandardowa funkcja ułatwiająca obsługę błędów (dostępna w glibc)
 #include <​arpa/​inet.h>​ #include <​arpa/​inet.h>​
  
 int main(){ int main(){
     // Ustawienie "​podpowiedzi"​ - sterowanie jakie wyniki chcemy otrzymać:     // Ustawienie "​podpowiedzi"​ - sterowanie jakie wyniki chcemy otrzymać:
-    addrinfo hints {};+    addrinfo hints {};    // uwaga: puste 'list initialization'​ zeruje całą strukturę
     hints.ai_family ​  = AF_INET; ​        // tylko IPv4 (AF_INET)     hints.ai_family ​  = AF_INET; ​        // tylko IPv4 (AF_INET)
     hints.ai_protocol = IPPROTO_UDP; ​    // protokół UDP     hints.ai_protocol = IPPROTO_UDP; ​    // protokół UDP
Linia 80: Linia 95:
     addrinfo * resolved;     addrinfo * resolved;
     ​     ​
 +    // Z sieci bezprzewodowej PP (lub innych używających serwerów nazw z podsieci 150.254.5.0/​24)
 +    // proszę zmienić "​pool.ntp.org"​ na "​onet.pl"​ - Dział Obsługi i Eksploatacji z niezrozumiałych
 +    // przyczyn cenzuruje odpowiedzi z DNS 
     int res = getaddrinfo("​pool.ntp.org",​ "​ntp",​ &hints, &​resolved);​     int res = getaddrinfo("​pool.ntp.org",​ "​ntp",​ &hints, &​resolved);​
     ​     ​
Linia 107: Linia 125:
     ​     ​
     char ip[40]; // maks. długość IP(v6) jako tekst: 8 bloków po 4 znaki oddzielone ':'​     char ip[40]; // maks. długość IP(v6) jako tekst: 8 bloków po 4 znaki oddzielone ':'​
 +                 // można użyć stałą NI_MAXHOST określającą maksymalną długość nazwy domenowej ​
     for(addrinfo * it = resolved; it; it=it->​ai_next){     for(addrinfo * it = resolved; it; it=it->​ai_next){
         // funkcja getnameinfo tłumaczy dowolny sockaddr na tekst         // funkcja getnameinfo tłumaczy dowolny sockaddr na tekst
sk2/sockets_netdbs.1571661385.txt.gz · ostatnio zmienione: 2019/10/21 14:36 przez jkonczak