为何accept()调用需使用空的sockaddr结构体?
关于accept()第二个参数的困惑解答
嘿,我太懂这种看着自己写的代码却摸不着头脑的感觉了——当初我第一次啃socket编程的时候,对着accept()的这几个参数也卡了好久!咱们来一步步拆解你的疑问:
首先要澄清一个关键误解:你代码里的struct sockaddr_in client不是必须为空,它只是一个预先分配好内存的空结构体,等着内核往里面填数据而已。
这个参数到底是干嘛的?
accept()的第二个参数(struct sockaddr*类型),是给内核提供的一个缓冲区,内核会把发起连接的客户端的IP地址和端口信息填充到这个缓冲区里。简单说,就是让你的程序能知道“是谁在连我的服务”。
看你这段代码:
struct sockaddr_in client; size_t size = sizeof(client); if((nds=accept(ds,(struct sockaddr*)&client,&size)) <0) { perror("accept"); close(ds); exit(-1); }
你提前声明了client结构体,把它的地址&client传给accept(),内核就会把客户端的网络地址数据(比如IP、端口)写入这个结构体。而第三个参数&size是告诉内核这个缓冲区的大小,accept返回后,size会被更新为实际写入的地址数据长度(对于IPv4的sockaddr_in来说,这个值一般就是sizeof(struct sockaddr_in))。
那什么时候可以传空?
如果你写的服务根本不需要知道客户端是谁(比如某些只处理数据、不关心来源的服务),那完全可以把第二个参数传NULL,第三个参数也传NULL,比如:
nds = accept(ds, NULL, NULL);
这时候内核就不会填充任何地址信息,你也省掉了声明结构体的步骤。
再总结一下
- 你代码里的结构体不是“为空”,是预先准备好内存,等待内核写入客户端地址数据
- 这个参数的核心作用是让你的程序获取发起连接的客户端的网络信息
- 不需要客户端信息时,直接传
NULL即可,不用声明这个结构体
内容的提问来源于stack exchange,提问作者davigzzz
相关产品推荐
相关产品推荐

