As the title says, I'm thinking about using a small library to do just that: resolve a hostname to an ip address, without having me to rewrite the code for windows & linux.
Anyonw have recommendations for a smaller simple lib to achieve that?
As the title says, I'm thinking about using a small library to do just that: resolve a hostname to an ip address, without having me to rewrite the code for windows & linux.
Anyonw have recommendations for a smaller simple lib to achieve that?
As SeanMiddleditch pointed out, getaddrinfo() is probably your best bet. The following is a great guide on socket programming. I used it extensively as a reference when I was learning about sockets.
http://beej.us/guide/bgnet/output/print/bgnet_A4.pdf
If you scroll down to page 20 (16) (Chapter 5.1. getaddrinfo()) there's a complete example which does exactly what you asked for.
You may have to adjust a few things here and there to get it working on Windows (e.g. call WSAStartup() and WSACleanup() and include the right headers), but by and large it works the same way on Windows.
anyone who considers compiling on MingW to be "ported to Windows" should be thrown out of a window
Can you elaborate some more on why you take this stance?
I've come to the conclusion that writing cross platform software is a lot easier for everyone if you drop support for the MSVC compiler. It's non-compliant in many areas and is a pain to configure properly. As such it only causes headaches and additional overhead when writing your build scripts.
I find it disappointing that porting an entire POSIX compliant environment and toolchain to Windows is easier to do than supporting the MSVC compiler, but that's how it is.
EDIT:
Just got the code from the PDF file I linked to work using MSVC:
#include <stdio.h>
#include <string.h>
#include <WinSock2.h>
#include <WS2tcpip.h> // INET6_ADDRSTRLEN
static WSADATA g_wsa_data;
char net_init(void)
{
return (WSAStartup(MAKEWORD(2, 2), &g_wsa_data) == NO_ERROR);
}
void net_deinit(void)
{
WSACleanup();
}
void net_dns_resolve(const char* hostname)
{
struct addrinfo hints, *results, *item;
int status;
char ipstr[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; /* AF_INET6 to force version */
hints.ai_socktype = SOCK_STREAM;
if((status = getaddrinfo(hostname, NULL, &hints, &results)) != 0)
{
fprintf(stderr, "failed to resolve hostname \"%s\": %s", hostname, gai_strerror(status));
return;
}
printf("IP addresses for %s:\n\n", hostname);
for(item = results; item != NULL; item = item->ai_next)
{
void* addr;
char* ipver;
/* get pointer to the address itself */
/* different fields in IPv4 and IPv6 */
if(item->ai_family == AF_INET) /* address is IPv4 */
{
struct sockaddr_in* ipv4 = (struct sockaddr_in*)item->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
}
else /* address is IPv6 */
{
struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)item->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
/* convert IP to a string and print it */
inet_ntop(item->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\n", ipver, ipstr);
}
freeaddrinfo(results);
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "usage: %s <hostname>\n", argv[0]);
return -1;
}
net_init();
net_dns_resolve(argv[1]);
net_deinit();
return 0;
}
Don't forget to link Ws2_32.lib under Configuration Properties->Linker->Input.
Here's the code ported to Linux:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
char net_init(void)
{
return 1; /* nothing to do */
}
void net_deinit(void)
{
/* nothing to do */
}
void net_dns_resolve(const char* hostname)
{
struct addrinfo hints, *results, *item;
int status;
char ipstr[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; /* AF_INET6 to force version */
hints.ai_socktype = SOCK_STREAM;
if((status = getaddrinfo(hostname, NULL, &hints, &results)) != 0)
{
fprintf(stderr, "failed to resolve hostname \"%s\": %s", hostname, gai_strerror(status));
return;
}
printf("IP addresses for %s:\n\n", hostname);
for(item = results; item != NULL; item = item->ai_next)
{
void* addr;
char* ipver;
/* get pointer to the address itself */
/* different fields in IPv4 and IPv6 */
if(item->ai_family == AF_INET) /* address is IPv4 */
{
struct sockaddr_in* ipv4 = (struct sockaddr_in*)item->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
}
else /* address is IPv6 */
{
struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)item->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
/* convert IP to a string and print it */
inet_ntop(item->ai_family, addr, ipstr, sizeof ipstr);
printf(" %s: %s\n", ipver, ipstr);
}
freeaddrinfo(results);
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
fprintf(stderr, "usage: %s <hostname>\n", argv[0]);
return -1;
}
net_init();
net_dns_resolve(argv[1]);
net_deinit();
return 0;
}