首页 > 解决方案 > 如何用 getaddrinfo 替换 inet_pton

问题描述

考虑 inet_pton 函数:

#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst)

据我了解,该函数以点分十进制形式的IP地址字符串作为输入(src)并将该字符串转换为字节形式,这是某些网络编程任务所必需的。事实上, src 被转换为一个结构 in_addr,它被复制到 dst(假设 af = AF_INET)。在这个结构中,应该有一个字节形式的 IP 地址条目(如果我错了,请纠正我!)。

我希望能够使用 inet_pton,但不是以点分十进制形式提供 src,而是想提供一个可以由我的 DNS 服务器解析的名称。

示例:而不是inet_pton(AF_INET, "10.70.1.114", buf)我想使用inet_pton(AF_INET, "myPC", buf)

我在想,也许我可以用getaddrinfoand getnameinfobefore 来解析我的名字。我正在考虑这样的功能:

char* resolvename(const char* name)
{
    struct addrinfo *infoptr, hints;
    char host[256];

    hints.ai_family=AF_INET;
    int result = getaddrinfo(name,NULL,&hints,&infoptr);
    if(result){
        fprintf(stderr, "getaddrinfo: %s\n", gai_stderror(result));
        exit(1);
        }
    getnameinfo(infoptr->ai_addr, infoptr->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);

    return host; 

}

然后我应该能够这样做:

mySrc = resolvename("myPC");
inet_pton(AF_INET, mySrc, buf);

这有任何意义吗?只是说:我没有任何网络编程经验。所有这些功能对我来说都很新,所以请赐教!

标签: c++socketsnetwork-programming

解决方案


char host[256];
...
return host; 

您返回指向自动数组的指针。该数组在作用域结束时自动销毁,因此您返回一个悬空指针。通过悬空指针间接的行为是未定义的。

此外,由于调用失败freeaddrinfo,您会泄漏内存。

getaddrinfo返回 的列表sockaddr,其中已经包含字节形式的 IP。如何将其取出的示例:

for (; infoptr; infoptr = infoptr->ai_next) {
    if (infoptr->ai_family == AF_INET) {
        assert(infoptr->ai_addrlen == sizeof(sockaddr_in));
        sockaddr_in addr;
        std::memcpy(&addr, infoptr->ai_addr, sizeof addr);
        std::memcpy(buf, addr.sin_addr, sizeof addr.sin_addr);
        break;
    }
}

如果您非常聪明,理论上可能有一种方法可以使用 offsetof 摆脱中间 memcpy 到 local sockaddr_in


推荐阅读