我是 C 编程新手,目前正在学习 Unix 套接字编程。
我的问题是绑定(bind)函数的第二个参数实际上是什么?
int main(){
int mysocket;
int portno = 5004;
mysocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr, cli_addr;
struct sockaddr_in *p = &serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
bind(mysocket, p, sizeof(serv_addr));
}
我尝试传递 p
、*p
,但不起作用。
最佳答案
bind()的第二个参数是一个指向结构体的指针,该结构体描述了套接字要绑定(bind)到的本地接口(interface)(第三个参数是该结构体的字节大小)。
bind()
采用 sockaddr*
指针作为输入,但它实际上接受任何与地址族匹配的 sockaddr_...
结构套接字(sockaddr_in
表示 AF_INET
,sockaddr_in6
表示 AF_INET6
,sockaddr_un
表示 AF_UNIX
等)。
曾几何时,只有 sockaddr
存在(对于 AF_INET
),以及 BSD 套接字 API(特别是 bind()
、 accept()
、connect()
和 get(sock|peer)name()
) 是围绕 sockaddr
设计的。后来,当引入新的地址族时,创建了 sockaddr_in
作为之前 sockaddr
所表示的内容(IPv4 地址)的直接替代。但socket函数接口(interface)已经是一成不变的,无法更改。这就是为什么在调用此类函数时需要 sockaddr*
类型转换。所有 sockaddr_...
结构(包括 sockaddr
本身)都以 16 位 family
标识符开头,因此使用此类类型转换(协调与相关的字节大小参数)是安全的。
现在,在您的示例中,p
在第二个参数中传递,并且 p
声明为 Struct sockaddr_in *p = &serv_addr;
,所以你实际上传入了 serv_addr
的内存地址(只有当参数声明为 void*
时,此代码才会编译,否则你将需要一个 sockaddr*
类型转换 - 这是平台相关的!)。 serv_addr
填充有 IPv4 地址(INADDR_ANY
,又名 0.0.0.0
)和端口号(portno
,按网络字节顺序)。第三个参数设置为 sizeof(serv_addr)
。
因此,在该大小值和 serv_addr.sin_family
设置为 AF_INET
之间,bind()
知道您正在传递 sockaddr_in
结构,并将相应地验证和使用它。
关于c - bind() 套接字函数的第二个参数是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47821106/