przejście do zawartości
Jan Kończak
Narzędzia użytkownika
Zaloguj
Narzędzia witryny
Narzędzia
Pokaż stronę
Poprzednie wersje
Odnośniki
Ostatnie zmiany
Menadżer multimediów
Indeks
Zaloguj
Ostatnie zmiany
Menadżer multimediów
Indeks
Jesteś tutaj:
start
»
sk2
»
sockets_netdbs
sk2:sockets_netdbs
Ta strona jest tylko do odczytu. Możesz wyświetlić źródła tej strony ale nie możesz ich zmienić.
====== Zmiana adresu domenowego na IP ====== ===== Tradycyjna funkcja gethostbyname ===== Najstarsze funkcje do zmiany to ''gethostbyname'' i ''gethostbyaddr''. Funkcje są przestarzałe i powszechnie używane. Problemy z ich działaniem obrazuje poniższy kod: <code cpp ghbn.cpp> #include <iostream> #include <netdb.h> #include <arpa/inet.h> #include <thread> #include <atomic> #include <unistd.h> using namespace std; void print(hostent* ret){ cout << ret->h_name << endl; for(auto it = ret->h_addr_list; *it; ++it){ cout << " " << inet_ntoa(*((in_addr*)*it)) << endl; } } int main(int argc, char **argv) { atomic<bool> wait1 {true}, wait2 {true}; std::thread t1([&]{ while(wait1.load()); // cout << "About to invoke gethostbyname(\"spam.org\")" << endl; gethostbyname("spam.org"); // cout << "gethostbyname(\"spam.org\") finished" << endl << endl; wait2.store(false); sleep(1); }), t2([&]{ // cout << "About to invoke gethostbyname(\"fc.put.poznan.pl\")" << endl; hostent* ret = gethostbyname("fc.put.poznan.pl"); // cout << "gethostbyname(\"fc.put.poznan.pl\") finished" << endl << endl; wait1.store(false); while(wait2.load()); // cout << "Printing the result of gethostbyname(\"fc.put.poznan.pl\")" << endl; print(ret); }); t1.join(); t2.join(); return 0; } </code> //Zadanie 1.// Przetestuj powyższy kod. Zastanów się jak uniknąć problemu, który pokazuje powyższy kod. ===== Rozszerzenia GNU ===== <html><small></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]]) <code cpp> hostent he, *resptr; int status, retval; char buffer[4096]; retval = gethostbyname_r("fc.put.poznan.pl", &he, buffer, sizeof(buffer), &resptr, &status); if(retval) error(1,0,"gethostbyname_r error: %s", hstrerror(status)); if(!resptr) error(1,0,"empty result"); print(resptr); </code> <html></small></html> ===== 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''. Składnia: <code cpp> int getaddrinfo( // zwraca 0 (ok) lub -1 (błąd) 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 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) </code> Przykład użycia: <code cpp> #include <netdb.h> #include <error.h> // (funkcja error) #include <errno.h> // (zmienna errno) (...) // // znajdzie dowolne adresy, w tym IPv6, nie ustawi portu // addrinfo * aio; // int res = getaddrinfo("fc.put.poznan.pl", 0, 0, &aio); // znajdzie tylko adresy IPv4, ustawi port 13 addrinfo * aio, aih {.ai_flags=0, .ai_family=AF_INET, .ai_socktype=SOCK_STREAM}; int res = getaddrinfo("fc.put.poznan.pl", "13", &aih, &aio); if(res) error(1, errno, "getaddrinfo failed"); if(!aio) error(1, 0, "empty result"); cout << "fc.put.poznan.pl" << endl; for(addrinfo * it = aio; ; it=it->ai_next){ cout << " " << inet_ntoa(((sockaddr_in*)it->ai_addr)->sin_addr) << endl; if(!it->ai_next) break; } freeaddrinfo(aio); </code> //Zadanie 2.// Stwórz klienta TCP, który: * odczyta z listy argumentów adres i numer portu * użyje funkcji ''getaddrinfo'' z pustymi podpowiedziami * utworzy socket korzystając z rodziny adresów zwróconej przez ''getaddrinfo'' * połączy się funkcją connect korzystając ze struktury sockaddr i informacji o jej długości zwróconej przez ''getaddrinfo''
sk2/sockets_netdbs.1508763995.txt.gz
· ostatnio zmienione: 2017/10/23 15:06 przez
jkonczak
Narzędzia strony
Pokaż stronę
Poprzednie wersje
Odnośniki
Złóż / rozłóż wszystko
Do góry