Reputation: 143
I am creating a server that send message to all clients if one client send message to server. I tested my server with telnet and two other clients in the in my computer. It works find if I use "localhost" as value in the first argument of function getaddrinfo. BUt when I replace it with my ip address, which I obtain by searching on google, it failed to bind socket to the port. Why that happens?
This works well when I test my telnet.
if ((rv = getaddrinfo("localhost", PORT, &hints, &ai)) != 0) {
fprintf(stderr, "selectserver: %s\n", gai_strerror(rv));
exit(1);
}
for(p = ai; p != NULL; p = p->ai_next) {
listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (listener < 0) {
continue;
}
// lose the pesky "address already in use" error message
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) {
close(listener);
continue;
}
break;
}
The program fails to bind if I specified the IP addresss Note: that I replaced my IP addresss with the "xx.xxx.xxx.xxx"
if ((rv = getaddrinfo("xx.xxx.xxx.xxx", PORT, &hints, &ai)) != 0) {
fprintf(stderr, "selectserver: %s\n", gai_strerror(rv));
exit(1);
}
Upvotes: 0
Views: 2411
Reputation: 15642
It is most unusual to want to bind to "localhost"
or to your external IP address. Most computers in this day and age don't have an external IP address (the one that Google sees), because there's a router and a demilitarized zone between them and the internet. If you want to expose a service that's visible to your LAN to the internet, then you'll need to configure your router to forward connections, which is a topic that's more suitable for the networking variant of Stack Overflow.
Providing your hints.ai_flags = AI_PASSIVE
, you should be able to use NULL
in place of "localhost"
and getaddrinfo
will return a list of all suitable interfaces that you can bind on. If your hints.ai_flags
doesn't contain AI_PASSIVE
, then there's no guarantee that you can bind on the interfaces returned. Should you choose to use a string here, the AI_PASSIVE
flag will be ignored anyway...
In your code, you're creating multiple sockets one by one, discarding the previously created as you create the next one... That's a resource leak, and possibly the cause for the problem you've noticed too. Perhaps you intended to store your multiple socket descriptors into an array, and bind them one at a time?
Don't forget to freeaddrinfo
once you're done with ai
. In the example below I've used PF_UNSPEC
together with SOCK_STREAM
to listen on both IPV4 and IPV6 interfaces (as well as any other stream types), but these can be changed to bind to other types of addresses.
#define BIND_ADDR NULL
#define BIND_PORT "1234"
struct addrinfo *ai;
int rv = getaddrinfo(BIND_ADDR,
BIND_PORT,
&(struct addrinfo){ .ai_family = PF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_flags = AI_PASSIVE },
&ai)
if (rv != 0) {
fprintf(stderr, "selectserver: %s\n", gai_strerror(rv));
exit(1);
}
size_t ai_size = 0;
for (struct addrinfo *a = ai; a != NULL; a = a->ai_next) {
ai_size++;
}
int socket[ai_size] = { 0 };
size_t x = 0;
for (struct addrinfo *a = ai; a != NULL; a = a->ai_next) {
socket[x++] = socket(a->ai_family, a->ai_socktype, a->ai_protocol);
/* ... */
}
freeaddrinfo(ai);
/* ... */
Upvotes: 1