Sign in to follow this  

C++ cross platform resolve hostname to ip library

This topic is 834 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Only problem with that one is that it's limited to the POSIX OSes (and MingW for nominal Windows support, but anyone who considers compiling on MingW to be "ported to Windows" should be thrown out of a window).

I don't know any particular good library for this, other than just using the standard POSIX/Winsock function getaddrinfo.

Share this post


Link to post
Share on other sites

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;
}
Edited by TheComet

Share this post


Link to post
Share on other sites

This topic is 834 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this