【问题标题】:Why is the address length parameter neccessary when binding a socket in C?为什么在 C 中绑定套接字时需要地址长度参数?
【发布时间】:2017-05-05 13:28:37
【问题描述】:

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

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

【问题讨论】:

    标签: c sockets system-calls


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 但是由于在创建套接字时已经声明了地址族,您是否没有明确说明您要传递的地址?
    【解决方案2】:

    有几种不同的套接字地址

    这些都有自己的sockaddr_* 结构,即sockaddr_in 代表AF_INETsockaddr_in6 代表AF_INET6,等等。

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

    【讨论】:

    • 所以长度是某种交叉检查,以防您“声明”了 AF_INET 但您使用的地址是 AF_INET6?
    • @Dai 我不认为这是完全正确的 - 如果传递的结构小于 比声明的协议系列所需的结构,我希望内核会抱怨>
    • @giomanda:理论上,即使对于单个地址系列,长度也可能会有所不同。请记住,这个套接字接口可以追溯到网络的起源。电话在那个时代非常普遍,电话号码是一种成熟的网络地址形式。具有固定地址长度的 IP 的成功出乎意料,而 IPv6 表明,具有固定地址长度也不是一个好主意。
    【解决方案3】:

    系统调用是独立于协议的,例如它们适用于

    • IPv4 (sockaddr_in)
    • IPv6 (sockaddr_in6)
    • Unix 域套接字 (sockaddr_un)

    所有这些都可能有不同长度的套接字描述。这就是为什么你必须指定相应结构的长度。

    【讨论】:

      【解决方案4】:

      绑定(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr))

      它需要三个参数,套接字文件描述符绑定的地址地址的大小被绑定

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

      这是一个限制

      例如我会处理如下

      if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
                { 
                 error("ERROR on binding");
                }
      

      【讨论】:

        猜你喜欢
        • 2011-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-28
        • 2014-03-05
        • 2012-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多