为什么在 socket 编程中 accept() 函数要使用 socklent_t *?

3
在C语言的socket编程中,accept()函数的声明如下:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

我可以理解sockfdstruct sockaddr * addr的用途。

但是为什么我们必须传递套接字长度的地址,而不是使用socklen_t。因为如果accept()函数需要该长度,则可以通过socklen_t获取它。为什么函数原型要以这种方式声明?

那么为什么要使用socklen_t *类型?


相关链接:https://dev59.com/5WHVa4cB1Zd3GeqPqtex - alk
socketlen_t 是一个 类型,用于声明一个 变量,该变量可以保存套接字地址的长度,这个长度本身因地址族而异。它并不代表那个长度本身。 - user207421
2个回答

5
在不关心所接受的套接字地址/协议族的代码中,可能会使用通用的sockaddr_storage结构体来保存结果。指向socklen_t的初始值是该存储空间的大小;在accept返回之后,它的值将是生成的对等端地址的实际大小。此外,一些地址/协议族,如AF_UNIX具有可变长度的地址,因此即使您知道类型,也可能无法知道其大小。

那么这是为了长度,因为它们无法获取大小,但它们知道类型吗? - Subinoy

4
  1. 为什么需要addrlen
  2. accept函数用于处理许多协议族,它们的addr结构可能具有不同的长度。

参数addr是指向sockaddr结构的指针。该结构体包含与通信层所知道的对等端套接字地址。返回的地址格式由套接字的地址族决定(参见socket(2)和相应的协议手册)。当addr为NULL时,没有填充任何内容;在这种情况下,addrlen未使用并且也应为NULL。

  1. 为什么要使用指针

addrlen参数是一个值结果参数:调用者必须将其初始化为包含addr指向的结构的大小(以字节为单位);返回时,它将包含对等方地址的实际大小。

  1. 为什么要使用socklen_t

socklen_t类型 accept()的第三个参数最初被声明为int *(在libc4和libc5以及许多其他系统中是这样的,例如4.x BSD,SunOS 4,SGI);POSIX.1g草案标准希望将其更改为size_t *,这就是SunOS 5的情况。后来的POSIX草案有socklen_t *,Single UNIX规范和glibc2也是如此。引用Linus Torvalds的话:

"任何理智的库都必须使“socklen_t”与int大小相同。其他任何情况都会破坏任何BSD套接字层内容。POSIX最初将其设置为size_t,我(以及希望其他人,但显然不太多)非常大声地向他们抱怨。将其设置为size_t是完全错误的,因为例如在64位体系结构上,size_t很少与“int”大小相同。它必须与“int”大小相同,因为这就是BSD套接字接口的定义。无论如何,POSIX的人最终有所作为,并创建了“socklen_t”。他们一开始不应该碰它,但一旦他们这样做了,他们觉得它必须具有命名类型,出于某些难以理解的原因(可能有人不喜欢因为做了最初的愚蠢事情而失去面子,所以他们悄悄地重命名了他们的错误)。”

参考:man accept,man socket


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接