我知道sockaddr_in用于IPv4,sockaddr_in 6用于IPv6.我感到困惑的是[6]中sockaddr和sockaddr_之间的区别.

有些函数接受sockaddr,有些函数接受sockaddr_insockaddr_in6,因此:

  • 规则是什么?
  • 为什么需要两种不同的结构?

而且因为这sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in)美元.

  • 这是否意味着如果我们需要支持IPv4和IPv6,我们应该始终使用sockaddr_in6来分配堆栈中的内存,并强制转换为sockaddr和sockaddr_in?

一个例子是:我们有一个套接字,我们想得到它的字符串ip地址(可以是ipv4或ipv6).

我们先拨打getsockname获得addr,然后根据addr.sa_family拨打inet_ntop.

这段代码有什么问题吗?

char ipStr[256];
sockaddr_in6 addr_inv6;
sockaddr* addr = (sockaddr*)&addr_inv6;
sockaddr_in* addr_in = (sockaddr_in*)&addr_inv6;

socklen_t len = sizeof(addr_inv6);
getsockname(_socket, addr, &len);

if (addr->sa_family == AF_INET6) {
    inet_ntop(addr_inv6.sin6_family, &addr_inv6.sin6_addr, ipStr, sizeof(ipStr)); 
    // <<<<<<<<IS THIS LINE VALID, getsockname expected a sockaddr, but we use 
    // it output parameter as sockaddr_in6.
} else {
    inet_ntop(addr_in->sin_family, &addr_in->sin_addr, ipStr, sizeof(ipStr));
}

推荐答案

我不想回答我的问题.但为了在这里提供更多可能对其他人有用的信息,我决定回答我的问题.

之后深入挖掘linux的源代码.以下是我的发现,可能有多个协议都实现了getsockname.每个都有自己的下划线地址数据结构,例如,对于IPv4是sockaddr_in,IPV6是sockaddr_in6,对于AF_UNIX套接字是sockaddr_un.sockaddr被用作这些API签名中的公共数据支柱.

这些API将根据memcpy的另一个参数length将SocketAddress_in或SockeAddr_in 6或SockeAddr_un复制到SockeAddr.

并且所有的数据结构都以相同类型的字段sa_family开始.

基于这些原因,代码片段是有效的,因为sockaddr_insockaddr_in6都有sa_family,然后我们可以在判断sa_family之后将其转换为正确的数据结构以供使用.

顺便说一句,我不确定为什么根据sockaddr大小分配内存的sizeof(sockaddr_in6) > sizeof(sockaddr)对于IPv6来说是不够的(这很容易出错),但我猜这是因为历史原因.

C++相关问答推荐

强制转换为“超类”并返回 C 是否违反严格别名?

我可以在同一个文件中使用 time.h 中的两个 tm 结构吗?

使用R的`.C`接口处理读/写文件

引用如何出现在可从 C 代码调用的函数的签名中?

C 编程语言中有范围运算符吗?

C 是否有 [[nodiscard]] 机制在忽略值时发出警告?

libcurl 放置数据流而不是文件

为双指针的顶层分配内存

您可以使用 C 内联汇编来对齐指令吗? (没有编译器优化)

C中指向结构的指针与指向数组的指针

如何仅将 C 中 for 循环中的三个最大整数分配给三个单独的变量?

从两个 32 位定时器计数器读取 64 位定时器值时,正确的 ARM64(AArch64)数据内存屏障使用是什么?

找到一种在 C 中调用具有不同参数的函数的方法

如何让我的应用程序找到 gettext 翻译?

printf() - 如何添加前导零 + 填充

使用 strstr 查找子字符串的所有实例会导致奇怪的字符串格式

项目中包含程序集文件时,来自 mmap 的意外 exec 权限

为什么glibc的strlen需要这么复杂才能快速运行?

“使用带二进制位运算符的有符号整数操作数” - 使用无符号短时

为什么要在 C 和 C++ 项目中创建 include/ 目录?