recvfrom
要求第5个参数是指向sockaddr
结构的指针,第6个参数是指向socklen_t
的指针。
man recvfrom (3)
说:
如果地址的实际长度大于 提供的sockaddr结构,存储的地址应被截断。
我不知道如何检索AF_INET6地址系列的发送套接字地址,因为sockaddr_in6
的大小大于sockaddr
因此会被{{1}截断}。
我是否认为recvfrom
无法检索大于recvfrom
的地址?
即使我将sizeof(sockaddr)
的实例定义为sockaddr_in6
并将其传递给sockaddr*
并将其传递给recvfrom
,该功能也无法知道空间可用于存储地址?
答案 0 :(得分:7)
您将sockaddr_in6
(类型转换)的指针和sockaddr_in6
结构的大小作为参数传递:
struct sockaddr_in6 in6;
socklen_t len6 = sizeof(in6);
recvfrom(sock, buf, buflen, (struct sockaddr *) &in6, &len6);
由于您将正确的长度传递给函数,它将起作用。
答案 1 :(得分:7)
将其强制转换为sockaddr*
。
此外,人们经常使用sockaddr_storage
,因为它是defined
标题应定义sockaddr_storage结构。 该结构应为:
- 足够大以容纳所有支持的协议特定地址结构
- 在适当的边界对齐,以便指向它的指针可以作为指向协议特定地址结构的指针并用于 访问这些结构的字段而没有对齐问题
通过这种方式,您可以将它用于多种协议,因此您不会受到IPv6或IPv4的限制。
所以你可以做到
struct sockaddr_storage addr;
socklen_t sa_len = sizeof(addr);
recvfrom (sock, buffer, sizeof (buffer), (struct sockaddr*) &addr, &sa_len);
如果你需要知道sockaddr的kinf是什么,你可以检查每个sockaddr结构中存在的强制sa_family_t ss_family
字段。