struct addrinfo和struct sockaddr有什么区别?

39
据我所了解,结构体addrinfo用于准备套接字地址结构,而结构体sockaddr包含套接字地址信息。但这实际上是什么意思呢?struct addrinfo包含指向struct sockaddr的指针。为什么要将它们分开?我们为什么不能将sockaddr中的所有内容合并到addr_info中?
我只是猜测,它们被分开的原因是在传递结构时节省空间。例如,在bind()调用中,它只需要端口号和Internet地址。因此,这两者被分组在一个结构体sockaddr中。因此,我们只需传递这个小的结构体,而不是较大的struct addrinfo结构体吗?
struct addrinfo {
    int              ai_flags;     // AI_PASSIVE, AI_CANONNAME, etc.
    int              ai_family;    // AF_INET, AF_INET6, AF_UNSPEC
    int              ai_socktype;  // SOCK_STREAM, SOCK_DGRAM
    int              ai_protocol;  // use 0 for "any"
    size_t           ai_addrlen;   // size of ai_addr in bytes
    struct sockaddr *ai_addr;      // struct sockaddr_in or _in6
    char            *ai_canonname; // full canonical hostname

    struct addrinfo *ai_next;      // linked list, next node
};

struct sockaddr {
    unsigned short    sa_family;    // address family, AF_xxx
    char              sa_data[14];  // 14 bytes of protocol address
}; 
1个回答

31

struct addrinfogetaddrinfo()返回,并且在成功时包含指定主机名和/或服务的此类struct的链表。

ai_addr成员实际上不是struct sockaddr,因为该struct仅仅是一个通用的struct,它包含所有其他struct的公共成员,并用于确定您实际拥有哪种类型的struct。根据您传递给getaddrinfo()的内容以及该函数发现的内容,ai_addr实际上可能是指向struct sockaddr_instruct sockaddr_in6或其他任何适合该特定地址条目的内容的指针。这就是它们被"分离"的一个很好的原因,因为该成员可能指向一堆不同类型的struct之一,如果您试图将所有成员硬编码到struct addrinfo中,则无法实现,因为这些不同的struct具有不同的成员。

如果您有一个主机名,那么这可能是获取此信息的最简单方法,但并不是唯一的方法。对于IPv4连接,如果您想要并且有数据可以这样做,您可以自己填充struct sockaddr_in结构,并避免调用getaddrinfo()的繁琐操作,如果它需要去互联网收集信息,则可能需要等待。您甚至可以完全不使用struct addrinfo


如果您只知道主机名而不知道主机的IP地址,getaddrinfo()是否更有用?因为如果您是客户端(并且您知道服务器的IP),并且调用getaddrinfo并发送服务器的IP地址,则似乎有点重复,并且getaddrinfo()返回一个带有您已经知道的所有详细信息的addrinfo结构。这个评论只是在重申您所说的内容...抱歉。 - user2782310
4
如果您在命令行中输入IP地址并以字符串形式获取了该地址,则getaddrinfo()有时非常方便。您可以自己解析它并将其转换为struct sockaddr_in所需的32位整数格式,但有时您可能认为让getaddrinfo()来做这件事更容易。如果您已经将IP地址格式化为可以放入struct sockaddr_in的格式,则调用getaddrinfo()通常是没有意义的。 - Crowman

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