为什么必须在套接字函数中传递sizeof?

时间:2012-10-26 12:27:07

标签: c sockets

我正在研究C中的套接字编程,我很好奇为什么你必须在bind()和{{1}这样的函数中传递参数一长度的参数}}? 为什么不在函数内部使用connect()

2 个答案:

答案 0 :(得分:6)

因为它提供了一种简单的方法来处理具有相同API的许多不同类型的协议。

由于套接字可以使用许多不同的底层协议(如@larsman所指出的),因此调用无法准确地知道它正在传递给哪种类型的结构。各种struct sockaddr类型都有一些基本的“继承”。

此外,它提供了一些前向兼容性;对于一个版本的库编译的二进制文件可能是针对更高版本运行的,其中地址类型可能已经增长(例如支持IPv6)。

通过将调用者的大小的想法传递给被调用的函数,被调用的函数可以注意不要覆盖内存。

答案 1 :(得分:2)

我想你是

的第三个参数
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

你不能在函数内部执行sizeof(addr),因为那只会返回指针的大小,而不是指向的结构。 sizeof(struct sockaddr)也不起作用,因为不同的地址系列(本地套接字,IPv4,IPv6,外来网络协议)具有不同大小的sockaddr类似的类型。

例如,对于IPv4套接字,请调用

struct sockaddr_in my_addr;
// set up my_addr
bind(fd, (struct sockaddr *)my_addr, sizeof(struct sockaddr_in));

但对于本地(Unix)域套接字,您传递的sockaddr_un长度可能不同。

[在我的Linux机器上,sizeof(struct sockaddr_in) == 16sizeof(struct sockaddr_un) == 110。]

如果您习惯于面向对象的编程,那么您可以将sockaddr族视为具有动态类型的(浅)类层次结构。 struct sockaddr是抽象基类,bindconnect等是方法。由于C没有内置的动态类型,因此必须进行模拟,并且传递结构的大小是其中的一部分。