I am trying to use the function getaddrinfo
with a passive socket/listener instead of filling directly the old sockaddr
structure.
My purpose is to open a socket and bind it to a port. Essentially I am building a server.
I don't know why but getaddrinfo
returns 2 results; because of this in the loop below the second time I call bind it exit with an error saying "address already in use".
Do you know how to fix this and if it is correct to have it in a loop ?
struct addrinfo addr;
memset(&addr,0,sizeof(addrinfo));
addr.ai_family = AF_INET;
addr.ai_socktype = SOCK_STREAM;
addr.ai_protocol = 0;
addr.ai_flags = AI_PASSIVE;
struct addrinfo * rp,* result;
getaddrinfo( "localhost","59001",&addr,&result );
for( rp = result; rp != NULL; rp = rp->ai_next ){
int sd = socket( AF_INET, SOCK_STREAM, 0 );
if(-1==sd ){
printf( "error creating the socket %m");
return -1;
}
if( -1==bind( sd, result->ai_addr, result->ai_addrlen ) ){
printf( "error binding %m")
return -1;
}
if( -1== listen(sd, MAX_BACKLOG ) ){
std::cerr << "listen didn't work" << std::endl;
return -1;
}
}
There are a couple of things going on here. For the multiple results from getaddrinfo()
, that's because it returns an IPv4 address and a IPv6 address (you have both). As for the "address already in use", you need to set the SO_REUSEADDR
option. Put this between your calls to socket()
and bind()
:
int opval = 1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));