简体   繁体   中英

C++ Resolve a host IP address from a URL

给定Visual C++ 中的 URL,如何解析主机 IP 地址?

I'm not sure if there is a specific C++ class to do host name lookups, but you can always resort to plain C for such things. Here's my version which compiles and runs on Linux, Mac OS X, and Windows.


#include <stdio.h>

#ifdef _WIN32
#  include "winsock.h"
#else
#  include <netdb.h>
#  include <arpa/inet.h>
#endif

static void initialise(void)
{
#ifdef _WIN32
    WSADATA data;
    if (WSAStartup (MAKEWORD(1, 1), &data) != 0)
    {
        fputs ("Could not initialise Winsock.\n", stderr);
        exit (1);
    }
#endif
}

static void uninitialise (void)
{
#ifdef _WIN32
    WSACleanup ();
#endif
}

int main (int argc, char *argv[])
{
    struct hostent *he;

    if (argc == 1)
        return -1;

    initialise();

    he = gethostbyname (argv[1]);
    if (he == NULL)
    {
        switch (h_errno)
        {
            case HOST_NOT_FOUND:
                fputs ("The host was not found.\n", stderr);
                break;
            case NO_ADDRESS:
                fputs ("The name is valid but it has no address.\n", stderr);
                break;
            case NO_RECOVERY:
                fputs ("A non-recoverable name server error occurred.\n", stderr);
                break;
            case TRY_AGAIN:
                fputs ("The name server is temporarily unavailable.", stderr);
                break;
        }
    }
    else
    {
        puts (inet_ntoa (*((struct in_addr *) he->h_addr_list[0])));
    }

    uninitialise ();

    return he != NULL;
}

Once compiled, provide the host name as an argument:

$ ./a.out stackoverflow.com
69.59.196.211

To use the socket functions under Windows, you have to start by calling WSAStartup , specifying the version of Winsock you want (for your purposes, 1.1 will work fine). Then you can call gethostbyname to get the address of the host. When you're done, you're supposed to call WSACleanup. Putting that all together, you get something like this:

#include <windows.h>
#include <winsock.h>
#include <iostream>
#include <iterator>
#include <exception>
#include <algorithm>
#include <iomanip>

class use_WSA { 
    WSADATA d; 
    WORD ver;
public:
    use_WSA() : ver(MAKEWORD(1,1)) { 
        if ((WSAStartup(ver, &d)!=0) || (ver != d.wVersion))
            throw(std::runtime_error("Error starting Winsock"));
    }
    ~use_WSA() { WSACleanup(); }    
};

int main(int argc, char **argv) {
    if ( argc < 2 ) {
        std::cerr << "Usage: resolve <hostname>";
        return EXIT_FAILURE;
    }

    try { 
        use_WSA x;

        hostent *h = gethostbyname(argv[1]);
        unsigned char *addr = reinterpret_cast<unsigned char *>(h->h_addr_list[0]);
        std::copy(addr, addr+4, std::ostream_iterator<unsigned int>(std::cout, "."));
    }
    catch (std::exception const &exc) {
        std::cerr << exc.what() << "\n";
        return EXIT_FAILURE;
    }

    return 0;
}

Easy as follow:

On Linux

#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
int main()
{
struct hostent *he=gethostbyname("www.stackoverflow.com");
char *ip=inet_ntoa(*(struct in_addr*)he->h_addr_list[0]);
printf(ip);
}

On Windows

#include <stdio.h>
#include <winsock.h>
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
struct hostent *he=gethostbyname("www.stackoverflow.com");
char *ip=inet_ntoa(*(struct in_addr*)he->h_addr_list[0]);
printf(ip);
}

On Android

#include <stdio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main()
{
struct hostent *he=gethostbyname("www.stackoverflow.com");
char *ip=inet_ntoa(*(struct in_addr*)he->h_addr_list[0]);
printf(ip);
}

To compile for Android

Use these flags over arch-arm: -Wl,-s -lz -rdynamic -fPIE -pie

After done, run it via adb

adb push <binfile> /data/local/tmp

adb shell /data/local/tmp/<binfile>

Parse the URL to get the host name. Then call gethostbyname or the corresponding API on your platform to get the IP address(es). If you are parsing a HTTP header, look for the HostName header to determine the host name.

struct hostent *he;

if ((he = gethostbyname("localhost") == NULL) {
    // Handle error: Failed
}

The IP address will be in he->h_addr . Works on both windows, linux and most likely macos.

gethostbyname

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM