我正在研究C中的套接字编程,我很好奇为什么你必须在bind()
和{{1}这样的函数中传递参数和一长度的参数}}?
为什么不在函数内部使用connect()
?
答案 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) == 16
但sizeof(struct sockaddr_un) == 110
。]
如果您习惯于面向对象的编程,那么您可以将sockaddr
族视为具有动态类型的(浅)类层次结构。 struct sockaddr
是抽象基类,bind
,connect
等是方法。由于C没有内置的动态类型,因此必须进行模拟,并且传递结构的大小是其中的一部分。