Reputation: 5393
I've created code designed to bind a new socket to the computer's addresses for listening for incoming connections on a specific port. I'm using getaddrinfo. Is this the best way? It seems pointless converting the port integer to a string. Is there a way to do this with no need for sprintf?
bool CBSocketBind(void * socketID,u_int16_t port){
struct addrinfo hints,*res,*ptr;
int socketIDInt;
// Set hints for the computer's addresses.
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// Get host for listening
char portStr[6];
sprintf(portStr, "%u",port);
if (getaddrinfo(NULL, portStr, &hints, &res) != 0)
return false;
// Attempt to bind to one of the addresses.
for(ptr = res; ptr != NULL; ptr = ptr->ai_next) {
if ((socketIDInt = socket(ptr->ai_family, ptr->ai_socktype,ptr->ai_protocol)) == -1)
continue;
if (bind(socketIDInt, ptr->ai_addr, ptr->ai_addrlen) == -1) {
close(socketIDInt);
continue;
}
break; // Success.
}
freeaddrinfo(res);
if (ptr == NULL) // Failure
return false;
socketID = malloc(sizeof(int));
*(int *)socketID = socketIDInt; // Set socket ID
// Make socket non-blocking
fcntl(socketIDInt,F_SETFL,fcntl(socketIDInt,F_GETFL,0) | O_NONBLOCK);
return true;
}
Upvotes: 2
Views: 1720
Reputation: 60933
The design of getaddrinfo()
was intended to accommodate any network protocol, which may use a different designation for a particular service. The designation may not be numeric, or may use a larger number than the 16-bit integer port numbers used by TCP. For maximal flexibility a service name may be provided, which can be translated to a protocol and any other information specific to the protocol, e.g. ftp
→ IPv4 or IPv6 TCP port 21. If you know that you will always be using IPv4 or IPv6 and TCP then you can pass NULL
for the service name and fill in the port number yourself in the returned socket address structure (sin_port
field for IPv4 or sin6_port
field for IPv6). However, it is probably cleaner to just use sprintf()
; this will handle the different socket address structures used by IPv4 and IPv6, and the requirement to store the port number in network byte order, and may also allow you to support other future protocols without code changes.
Upvotes: 3
Reputation: 37928
The reason getaddrinfo()
takes a string rather than an integer is that the service doesn't have to be just a port. The user could, for example, ask for service "http".
Upvotes: 2
Reputation: 8542
That looks fairly idiomatic of how getaddrinfo()
is normally used in AI_PASSIVE
state. The stringified number is typical.
Upvotes: 1