使用inet_ntop,WSAAddressToString,recvfrom等函数还需要提供实际sockaddr结构的大小还是要提供的地址族?
sockaddr结构的前两个字节表示地址族,因此也表明它实际上是sockaddr_in还是sockaddr_in6。
那么附加sizeof(sockaddr_in / sockaddr_in6)和AF_INET / AF_INET6的原因是什么?
答案 0 :(得分:0)
sockaddr
是遗留类型。特定地址系列有更新的sockaddr_...
类型,例如IPv4的sockaddr_in
和IPv6的sockaddr_in6
,它们具有不同的字节大小。 API在通用sockaddr*
指针上运行,部分原因在于历史原因,部分原因在于灵活性。套接字API识别多种地址类型。您通常必须提供大小,以便API可以验证您的内存缓冲区是否足够大,可以根据指定的系列传递地址数据(IPv4为AF_INET
,IPv6为AF_INET6
。
在inet_ntop()
中,in_addr
和in6_addr
不包含地址系列,这就是您必须单独传递它的原因。您有责任确保为传入的输入类型指定正确的地址系列。
在WSAAddressToString()
中,指向输入缓冲区的sockaddr*
指针。您必须传递该缓冲区的已分配大小。例如,由于sockaddr_in
小于sockaddr_in6
,如果您分配sockaddr_in
但将其系列设置为AF_INET6
而不是AF_INET
,则缓冲区太小对于访问所有IPv6字段的函数,它将失败并出现WSAEFAULT
错误而不是崩溃。
在recvfrom()
中,sockaddr*
是指向输出缓冲区的指针。您必须预先分配它并传递分配的大小。如果您分配sockaddr_in
但收到IPv6数据包,则发件人的地址将不适合您的缓冲区,并且该函数将因WSAEFAULT
错误而失败。