使用O_NONBLOCK设置TCP套接字为非阻塞后 后续API是否都非阻塞?
问题
如果我通过fcntl(sockfd, F_SETFL, O_NONBLOCK);将TCP套接字描述符设置为非阻塞模式,该设置是否会让后续调用的read()/listen()/accept()等所有套接字API都变为非阻塞状态?
解答
结论是该设置仅对绑定了这个属性的单个套接字描述符sockfd生效,所有针对该描述符调用的套接字API都会遵循非阻塞逻辑,但不会影响其他独立的套接字描述符。
各常见API的具体行为如下:
read()/recv():对设置了非阻塞的sockfd调用时,若内核接收缓冲区无可用数据,不会阻塞等待新数据到达,直接返回-1,同时errno被设置为EAGAIN或EWOULDBLOCK。write()/send():对设置了非阻塞的sockfd调用时,若内核发送缓冲区剩余空间不足以容纳所有待发送数据,不会阻塞等待空间释放,要么返回成功写入的字节数(部分写入),要么返回-1且errno设为EAGAIN/EWOULDBLOCK。listen():本身不存在阻塞逻辑,仅负责将套接字切换为监听状态,无论套接字是否设置非阻塞都会立刻返回,非阻塞标志对它无实际影响。accept():如果sockfd是设置了非阻塞的监听套接字,调用时若已完成三次握手的连接队列为空,不会阻塞等待新连接建立,直接返回-1且errno设为EAGAIN/EWOULDBLOCK。
注意:POSIX标准规定
accept()返回的新连接套接字会继承监听套接字的非阻塞属性,Linux、BSD、macOS等主流系统都符合该规则,部分老旧特殊系统可能不兼容,保险起见可在拿到新连接套接字后手动重新设置一次非阻塞标志。
内容的提问来源于stack exchange,提问作者Franc
相关产品推荐
相关产品推荐

