为什么在C中绑定套接字时需要地址长度参数?

为什么在C中绑定套接字时需要地址长度参数?,c,sockets,system-calls,C,Sockets,System Calls,我开始在C中使用套接字,当我使用bind()系统调用将套接字绑定到地址时,我必须指定addrlen参数 为什么套接字中需要地址长度?有几种不同类型的套接字地址 它们都有自己的sockaddr\u*结构,即AF\u INET的sockaddr\u in,AF\u INET6的sockaddr\u in 6等 传递长度允许内核检查传递的数据是否与套接字类型一致。绑定函数(syscall)是通用函数,它必须处理几种类型的地址,IPv4、IPv6、蓝牙、unix套接字和。。。每种地址类型的大小可能不同于

我开始在C中使用套接字,当我使用bind()系统调用将套接字绑定到地址时,我必须指定addrlen参数


为什么套接字中需要地址长度?

有几种不同类型的套接字地址

它们都有自己的
sockaddr\u*
结构,即
AF\u INET
sockaddr\u in
AF\u INET6的
sockaddr\u in 6

传递长度允许内核检查传递的数据是否与套接字类型一致。

绑定函数(syscall)是通用函数,它必须处理几种类型的地址,IPv4、IPv6、蓝牙、unix套接字和。。。每种地址类型的大小可能不同于其他地址类型,因此您必须通过传递其大小来明确要传递的地址

bind是一个syscall,syscall只是一个包装函数,它在用户空间中用于与内核空间交互。当您通过socket syscalls创建套接字时,将在调用进程的文件描述符表中创建一条记录。记录本身包括套接字的类型。 当您调用bind并将地址传递给它时,地址应该复制到内核空间,但地址有多大?绑定系统调用不知道要绑定的套接字,因为在内核空间和用户空间绑定函数中创建的套接字记录及其相应的系统调用不知道所需的大小。实际上,绑定只是将地址数据复制到内核空间并通知内核的系统调用

另一方面,绑定无法在运行时确定地址时间,因为纯C中没有运行时类型检查

因此,此时绑定不知道地址,您应该指定地址大小,以便将地址结构完全复制到内核空间。

系统调用与协议无关,例如,它们应用于

  • IPv4(sockaddr_in)
  • IPv6(sockaddr_in6)
  • Unix域套接字(sockaddr\u un)
所有这些都可能具有不同长度的套接字描述。这就是为什么必须指定相应结构的长度。

bind(sockfd,(struct sockaddr*)&serv\u addr,sizeof(serv\u addr))

它有三个参数,套接字文件描述符,绑定到的地址,以及绑定到的地址的大小

为什么套接字中需要地址长度

这是一个界限

例如,我将处理它如下

if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
          { 
           error("ERROR on binding");
          }
if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
{ 
错误(“绑定错误”);
}

因此长度是某种交叉检查,以防您“声明”一个AF_INET,但是您使用的地址是AF_INET6?@Dai我不认为这是严格正确的-如果传递的结构小于声明的协议所需的结构,我希望内核会抱怨family@giomanda:理论上,即使是单个地址系列,长度也可能不同。记住,这个套接字接口可以追溯到网络的起源。在那个时代,电话是非常普遍的,电话号码是网络地址的一种固定形式。IP在固定地址长度方面的成功是意料之中的,IPv6表明使用固定地址长度也不是一个好主意。但是,既然您在创建套接字时已经声明了地址族,您不清楚要传递哪个地址吗?