I'm following Beej's guide on NP.
I did a few modifications and am trying to obtain the IP of my server program through getaddrinfo().
(original can be found here http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#simpleserver)
Below is the parts I've changed/added.
if ((rv = getaddrinfo(NULL, "0", &hints, &servinfo)) != 0) { //0 for random port?
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
//... some code emitted ...
//freeaddrinfo(servinfo); //I still need it!
printf("ip: %s\nport: %d\n",
inet_ntop(AF_INET, &((struct sockaddr_in *)p->ai_addr)->sin_addr, ip4, INET_ADDRSTRLEN),
ntohs(((struct sockaddr_in *)p->ai_addr)->sin_port)
);
The problem is that I get results
ip: 0.0.0.0
port: 0
Q1:I've read from a couple of websites saying that setting "0" for the port tells the OS that you want the next available port, not actually 0. Is this true?
Q2:I've also read that gethostbyname(gethostname(...)) can give you the machine's ip, but Beej said that these are superseded by getaddrinfo(). So, am I supposed to use getaddrinfo? Or gethostbyname?
Q3:Is there anything else I'm doing wrong?
It's returning exactly what you would expect it to.
From man getaddrinfo
:
If the AI_PASSIVE flag is specified in hints.ai_flags, and node is NULL, then the returned socket addresses will be suitable for bind(2)ing a socket that will accept(2) connections. The returned socket address will contain the "wildcard address" (INADDR_ANY for IPv4 addresses, IN6ADDR_ANY_INIT for IPv6 address). The wild‐card address is used by applications (typically servers) that intend to accept connections on any of the hosts's network addresses. If node is not NULL, then the AI_PASSIVE flag is ignored.
The code you link to sets hints.ai_flags
to AI_PASSIVE
and you're passing NULL
for node. The wildcard address is 0.0.0.0
. Working as specified. Binding to that address means you're binding to every IP address on your machine.
As for the port ... you're specifying "0"
which ... is exactly what you're getting back. You need to set it an actual port you wish to listen on as the example code you link to does.
Q1:I've read from a couple of websites saying that setting "0" for the port tells the OS that you want the next available port, not actually 0. Is this true?
Yes, but only after you have used bind()
to attach the address to a real socket. At that point, use getsockname()
to get the bound address from the socket; the port will be part of that.
Q2:I've also read that gethostbyname(gethostname(...)) can give you the machine's ip, but Beej said that these are superseded by getaddrinfo(). So, am I supposed to use getaddrinfo? Or gethostbyname?
Use getaddrinfo()
; it does all that gethostbyname()
did and more, and the interface sucks a lot less. (For example, it's typically thread-safe.)
Q3:Is there anything else I'm doing wrong?
There's no good defined concept of the server's IP address. Servers can have many due to things like multiple network cards (much more common for servers than desktop systems), and the one that the outside world knows it by might not be one of them (thanks to NAT firewalls). Occasionally, you can know exactly where the messages are coming from before the client connects — the most common option is to know that the client will be on localhost
— which is part of the information you set during bind()
but that's rare. You can find the address of the client once the connection has happened by using getpeername()
but NAT might still make that functionally useless. Such addresses are typically set in the app's config file during deployment.
If you only need the info for logging purposes, go right ahead. But beware of using it for anything else, as it doesn't actually tell you that much.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With