getnameinfo() - 反向 DNS 查询(IP 地址到主机名)C/C++

4
对于IP地址66.249.68.9(“dig-x”正确显示为“crawl-66-249-68-9.googlebot.com”),我的程序却声称它是ip68-9-0-0.ri.ri.cox.net。
我不在乎最终的实现方式是否类似下面的代码,只想能够从IPv4地址开始并以主机名结束。
额外的问题是,什么是服务?我认为我不需要它,并将使getnameinfo为空。但是,该程序正在输出“17145”作为serviceBuffer。
#include <string>
#include <iostream>
using namespace std;

#include <netdb.h> // struct sockaddr, AF_INET, NI_NAMEREQD, getnameinfo
#include <string.h> // memset
#include <arpa/inet.h> // inet_pton

int main() {
   const string IPAddress { "66.249.68.9" };

   struct sockaddr structSockAddr;
   memset(&structSockAddr, 0, sizeof(structSockAddr));

   structSockAddr.sa_family = AF_INET;
   int inetPtonReturnValue { inet_pton(AF_INET, IPAddress.c_str(), &structSockAddr.sa_data) };
   if(1 != inetPtonReturnValue) {
      cout << "inetPtonReturnValue : " << inetPtonReturnValue << endl; // 0 = src doesn't contain valid address, -1 = af isn't a valid family
   }

   char hostBuffer[10000];
   char serviceBuffer[1000];

   int getNameInfoReturnValue { getnameinfo(&structSockAddr, sizeof(structSockAddr), hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NAMEREQD) };

   if(0 != getNameInfoReturnValue) {
      cout << "getNameInfoReturnValue : " << getNameInfoReturnValue << endl
           << "gai_strerror() : " << gai_strerror(getNameInfoReturnValue) << endl;
   } else {
      cout << "IPAddress : " << IPAddress << endl
           << "hostBuffer : " << hostBuffer << endl
           << "serviceBuffer : " << serviceBuffer << endl;
   }
}

2
作为一种风格上的考虑,你这样做 int inetPtonReturnValue { inet_pton(AF_INET, IPAddress.c_str(), &structSockAddr.sa_data) }; 有什么原因,而不是直接将 inet_pton 赋值给 inetPtonReturnValue - Joe
你的实际问题是什么(不是“奖金”)? - Chris Laplante
Joe - 只喜欢使用花括号初始化。 - user1902689
Chris - 抱歉,实际问题是为什么我的程序会给出 hostBuffer "ip68-9-0-0.ri.ri.cox.net" 而不是正确答案 "crawl-66-249-68-9.googlebot.com"。 - user1902689
2个回答

3
当您调用inet_pton时,您使用了一个struct sockaddr,但是调用签名要求这是一个struct in_addr用于AF_INET(或struct in6_addr用于IPv6)。然后,您必须在稍后的函数中使用该结构来构建struct sockaddr
目前,您正在将一些字节写入包含实际IP地址的字段之前的字段中,因此在您的sockaddr字段中最终只有IP的最后两个八位字节。

0

以下是一个C++反向DNS查找的示例代码

// Variables
WSADATA wsaData = { 0 };
int iResult = 0;
DWORD dwRetval;
struct sockaddr_in saGNI;
char hostname[NI_MAXHOST];
char servInfo[NI_MAXSERV];
std::string ip = "YOUR_SERVER_IP";
int port = 25;

iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult == 0 /*initialization success*/) {
    saGNI.sin_family = AF_INET;
    saGNI.sin_addr.s_addr = inet_addr(ip.c_str());
    saGNI.sin_port = htons(port);

    dwRetval = getnameinfo((struct sockaddr*) & saGNI,
        sizeof(struct sockaddr),
        hostname,
        NI_MAXHOST, servInfo, NI_MAXSERV, NI_NUMERICSERV);

    if (dwRetval == 0) {
        // save hostname result
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接