C++ 从 URL 解析主机 IP 地址

问题描述 投票:0回答:7

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

c++ url ip
7个回答
13
投票

我不确定是否有特定的 C++ 类来执行主机名查找,但您始终可以使用纯 C 来执行此类操作。这是我的版本,可以在 Linux、Mac OS X 和 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;
}

编译后,提供主机名作为参数:

$ ./a.out stackoverflow.com
69.59.196.211

8
投票

要在 Windows 下使用套接字功能,您必须首先调用

WSAStartup
,指定您想要的 Winsock 版本(就您的目的而言,1.1 就可以正常工作)。然后你可以调用
gethostbyname
来获取主机的地址。完成后,您应该调用 WSACleanup。把所有这些放在一起,你会得到这样的东西:

#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;
}

2
投票

简单如下:

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);
}

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);
}

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);
}

为Android编译

在 arch-arm 上使用这些标志:-Wl,-s -lz -rdynamic -fPIE -pie

完成后,通过adb

运行它
adb push <binfile> /data/local/tmp

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

1
投票
struct hostent *he;

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

IP 地址将在

he->h_addr
中。适用于 Windows、Linux 以及最有可能的 Macos。


0
投票

解析 URL 以获取主机名。然后调用 gethostbyname 或您平台上相应的 API 来获取 IP 地址。如果您正在解析 HTTP 标头,请查找 HostName 标头以确定主机名。


0
投票
#include <winsock2.h>
#include <ws2tcpip.h>
using namespace std;

#pragma comment(lib, "ws2_32.lib")

int RSV2IP4(const char* hostname, char* ip4str, size_t ip4str_len) {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        //fprintf(stderr, "Failed to initialize Winsock\n");
        return 1;
    }

    struct addrinfo hints;
    struct addrinfo* result, * rp;
    int status;

    // Set up the hints structure to specify the desired options (IPv4, TCP).
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET; // IPv4
    hints.ai_socktype = SOCK_STREAM; // TCP socket

    // Use getaddrinfo to resolve the address.
    status = getaddrinfo(hostname, NULL, &hints, &result);
    if (status != 0) {
        //fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        WSACleanup();
        return 2;
    }

    // Iterate through the results to find the IPv4 address.
    for (rp = result; rp != NULL; rp = rp->ai_next) {
        struct sockaddr_in* ipv4 = (struct sockaddr_in*)rp->ai_addr;
        void* addr = &(ipv4->sin_addr);

        if (inet_ntop(AF_INET, addr, ip4str, ip4str_len) != NULL) {
            // Successfully resolved the IPv4 address.
            freeaddrinfo(result);
            WSACleanup();
            return 0;
        }
    }

    // Failed to resolve an IPv4 address.
    freeaddrinfo(result);
    WSACleanup();
    return 3;
}

-2
投票

gethostbyname

© www.soinside.com 2019 - 2024. All rights reserved.