将struct in_addr转换为文本

4

我想知道如果我有一个结构体 in_addr,如何将其转换回主机名?

2个回答

6
您可以通过将您的struct in_addr包装在struct sockaddr_in中来使用getnameinfo():
int get_host(struct in_addr addr, char *host, size_t hostlen)
{
    struct sockaddr_in sa = { .sin_family = AF_INET, .sin_addr = my_in_addr };

    return getnameinfo(&sa, sizeof sa, host, hostlen, 0, 0, 0);
}

1
+1 针对原问题的回答,但要使用现代接口! - R.. GitHub STOP HELPING ICE

5

现代代码不应直接使用struct in_addr,而应该使用sockaddr_in。更好的方法是根本不直接创建或访问任何类型的sockaddr结构,并通过getaddrinfogetnameinfo库调用完成所有操作。例如,要查找主机名或文本形式的IP地址:

struct addrinfo *ai;
if (getaddrinfo("8.8.8.8", 0, 0, &ai)) < 0) goto error;

获取地址的名称(或文本形式的IP地址,如果它没有反向解析):

if (getnameinfo(ai.ai_addr, ai.ai_addrlen, buf, sizeof buf, 0, 0, 0) < 0) goto error;

我只能想到另外一个需要使用 sockaddr 类型结构的场景,那就是在套接字上使用 getpeernamegetsockname,或者使用 recvfrom。在这种情况下,除非您事先知道地址族,否则应该使用 sockaddr_storage
我给出这个建议有三个原因:
  1. 使用这两个函数进行所有字符串到地址和回转换要容易得多,而不必单独编写所有情况(以处理查找失败并尝试将地址解析为 IP 等)。
  2. 以这种方式编码可以轻松支持 IPv6(以及潜在的其他非 IPv4 协议)。
  3. 旧的函数 gethostbynamegethostbyaddr 实际上已从最新版本的 POSIX 中删除,因为它们被认为过时/废弃/已损坏。

1
+1 但这并不是你正确使用 getaddrinfo 的方式;最后一个参数应该是指向指针的 struct addrinfo 类型。在成功返回后,必须使用 freeaddrinfo 来释放它。 - dreamlax
@dreamlax:当然。我漏掉了声明ai*。现在已经修复了。 - R.. GitHub STOP HELPING ICE
就像在其他最近关于释放内存的问题中一样,在仅执行一次查找(或在启动时执行少量/固定数量的查找 - 想想“ping”,“nc”,“wget”等)的程序中调用freeaddrinfo是不必要且有潜在危害的。释放资源仅在将在其生命周期内执行任意大量查找的程序中才有益。当然,仅对结果进行短暂使用并返回给调用者的库需要立即释放其资源。 - R.. GitHub STOP HELPING ICE

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