Próbuję zaprogramować kilka gniazd, więc po stronie serwera używam htonl(INADDR_ANY)
. O ile zrozumiałem, wydaje mi się, że ta funkcja generuje losowe IP (czy mam rację?). W rzeczywistości chcę powiązać moje gniazdo z moim localhost
. Ale jeśli to uruchomię
printf("%d",htonl(INADDR_ANY));
Otrzymuję 0 jako wartość zwracaną. Czy ktoś mógłby przynieść jakieś wyjaśnienie?
htonl(INADDR_ANY)
. Dokument mówi, że ta funkcja generuje losowe IP… ” To nie jest poprawne. Które dokumenty ci to mówią?Odpowiedzi:
bind()
odINADDR_ANY
robi NIE „wygenerować losowy IP”. To wiąże się gniazdo do wszystkich dostępnych interfejsów .W przypadku serwera zazwyczaj chcesz powiązać wszystkie interfejsy - nie tylko „localhost”.
Jeśli chcesz powiązać swoje gniazdo tylko z lokalnym hostem, składnia byłaby następująca
my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");
, a następnie callbind(my_socket, (SOCKADDR *) &my_sockaddr, ...)
.Tak się składa, że
INADDR_ANY
jest stałą równą zeru:http://www.castaglia.org/proftpd/doc/devel-guide/src/include/inet.h.html
# define INADDR_ANY ((unsigned long int) 0x00000000) ... # define INADDR_NONE 0xffffffff ... # define INPORT_ANY 0 ...
Jeśli jeszcze go nie znasz, zachęcam do zapoznania się z przewodnikiem Beej po programowaniu gniazd:
http://beej.us/guide/bgnet/
Ponieważ ludzie nadal to czytają, dodatkowa uwaga:
Również:
źródło
INADDR_LOOPBACK
zamiastinet_addr("127.0.0.1")
?INADDR_ANY
jest używany, gdy nie musisz wiązać gniazda z określonym adresem IP. Gdy używasz tej wartości jako adresu podczas wywoływaniabind()
, gniazdo akceptuje połączenia ze wszystkimi adresami IP maszyny.źródło
Aby powiązać gniazdo z hostem lokalnym , przed wywołaniem funkcji bind należy odpowiednio ustawić pole sin_addr.s_addr struktury sockaddr_in. Odpowiednią wartość można uzyskać przez
my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1")
lub przez
źródło
INADDR_ANY
instruuje nasłuchujące gniazdo, aby powiązało się ze wszystkimi dostępnymi interfejsami. To to samo, co próba nawiązania połączeniainet_addr("0.0.0.0")
. Dla kompletności wspomnę również, że istnieje również IN6ADDR_ANY_INIT dla IPv6 i jest to to samo, co próba połączenia się z::
adresem dla gniazda IPv6.#include <netinet/in.h> struct in6_addr addr = IN6ADDR_ANY_INIT;
Należy również pamiętać, że po powiązaniu gniazda IPv6 z
IN6ADDR_ANY_INIT
gniazdem zostanie on powiązany ze wszystkimi interfejsami IPv6 i powinien być w stanie akceptować połączenia od klientów IPv4 (chociaż adresy mapowane na IPv6).źródło
INADDR_ANY to stała o wartości 0. będzie to używane tylko wtedy, gdy chcesz łączyć się ze wszystkich aktywnych portów, których nie obchodzi ip-add. więc jeśli chcesz podłączyć jakiś konkretny adres IP, powinieneś wspomnieć o tym jako my_sockaddress.sin_addr.s_addr = inet_addr ("192.168.78.2")
źródło