【发布时间】:2011-01-10 05:54:23
【问题描述】:
如果给定 Visual C++ 中的 URL,我如何解析主机 IP 地址?
【问题讨论】:
-
当然。但是几乎每个操作系统的答案都不同。你要哪一个?
如果给定 Visual C++ 中的 URL,我如何解析主机 IP 地址?
【问题讨论】:
我不确定是否有特定的 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
【讨论】:
cl resolve.c /link ws2_32.lib,否则链接时会出现未定义符号错误。
h_errno 包含 NO_ADDRESS 而不是 HOST_NOT_FOUND。
gethostbyname 已被getaddrinfo 取代。静态缓冲区?只有 IPV4?加入21世纪! :P
要在 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;
}
【讨论】:
简单如下:
在 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 编译
在拱臂上使用这些标志:-Wl,-s -lz -rdynamic -fPIE -pie
完成后,通过adb
运行adb push <binfile> /data/local/tmp
adb shell /data/local/tmp/<binfile>
【讨论】:
struct hostent *he;
if ((he = gethostbyname("localhost") == NULL) {
// Handle error: Failed
}
IP 地址为he->h_addr。适用于 windows、linux 和最有可能的 macos。
【讨论】:
解析 URL 以获取主机名。然后在您的平台上调用 gethostbyname 或相应的 API 以获取 IP 地址。如果您正在解析 HTTP 标头,请查找 HostName 标头以确定主机名。
【讨论】:
gethostbyname?
【讨论】: