在C套接字编程中,accept()
声明如下:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
我可以理解sockfd
,struct sockaddr *addr
的用法。
但是为什么我们必须传递套接字长度的地址,它可能是socklen_t
。因为如果accept()
函数需要长度,那么它可以通过socklen_t
得到它。为什么以这种方式声明函数的原型?
那么使用socklen_t *
类型的原因是什么?
答案 0 :(得分:4)
在与其接受的套接字的地址/协议族不相关的代码中,它可能使用通用sockaddr_storage
结构来保存结果。指向socklen_t
的初始值是此存储的大小; accept
返回后的值是生成的对等地址的实际大小。此外,某些地址/协议系列(如AF_UNIX
)具有可变长度的地址,因此即使您知道该类型,您也可能不知道其大小。
答案 1 :(得分:2)
为什么需要addrlen
接受旨在处理大量的protocal家族,他们的addr结构可能有不同的长度。
参数addr是一个指向sockaddr结构的指针。这个结构充满了 对等套接字的地址,如通信层所知。确切的格式 返回addr的地址由套接字的地址族决定(参见socket(2)) 和各自的协议手册页)。当addr为NULL时,不会填充任何内容;在这 case,addrlen不使用,也应该是NULL。
addrlen参数是一个value-result参数:调用者必须将其初始化为包含 addr指向的结构的大小(以字节为单位);在返回它将包含 对等地址的实际大小。
socklen_t类型 accept()的第三个参数最初被声明为int *(并且是在...之下) libc4和libc5以及许多其他系统,如4.x BSD,SunOS 4,SGI);一个POSIX.1g草案 标准希望将其更改为size_t *,这就是SunOS 5的用途 POSIX草稿有socklen_t *,Single UNIX Specification和glibc2也是如此。 Quot- Linus Torvalds:
" 任何理智的库必须有" socklen_t"与int的大小相同。还要别的吗 打破任何BSD套接字层的东西。 POSIX最初确实使它成为size_t,而我(和 希望其他人,但显然不是太多)确实非常大声地抱怨他们。 使它成为size_t完全被打破,正是因为size_t很少是相同的 大小为" int"例如,在64位体系结构上。它必须与它的大小相同 " INT"因为那是BSD套接字接口。无论如何,POSIX人事件 - 盟友得到了一个线索,并创造了" socklen_t"。他们不应该在第一次触摸它 地方,但一旦他们这样做,他们觉得它必须有一个命名类型的一些不可思议的rea 儿子(可能有人不喜欢因为做了原来的愚蠢而失去了面子 事情,所以他们默默地重新命名他们的错误。"
参考:男人接受,男人插座