为何epoll示例中需调用setnonblocking设置连接套接字非阻塞?
setnonblocking(conn_sock)? setnonblocking(conn_sock)的核心作用是将连接套接字设置为非阻塞模式,让后续对该套接字的所有IO操作(如read/recv、write/send)不会阻塞当前线程。结合代码里的epoll使用场景,原因主要有三点:
适配边缘触发(EPOLLET)的特性
代码中给连接套接字注册事件时用了EPOLLIN | EPOLLET(边缘触发模式)。这种模式下,epoll仅会在套接字从"未就绪"变为"就绪"时通知一次——比如新数据到达时触发EPOLLIN,但如果没把缓冲区数据一次性读完,后续不会再触发通知,直到有新数据流入。如果套接字是阻塞的,调用read时若缓冲区剩余数据不足,read会一直阻塞等待新数据,直接卡住整个事件循环,导致其他就绪的文件描述符无法被处理,彻底破坏并发能力。避免阻塞事件循环,保障并发处理效率
哪怕用默认的水平触发(LT)模式,设置非阻塞也很关键:当多个连接同时就绪时,若其中一个连接的IO操作(如read/write)阻塞,整个线程会被挂起,无法处理其他连接的请求。非阻塞模式下,IO操作无法完成时会立即返回EAGAIN错误,你可以先跳过这个连接,优先处理其他就绪的fd,之后等epoll再次通知时再重试,保证事件循环的流畅性。契合epoll的异步IO设计初衷
epoll的核心价值是让线程只处理已就绪的IO事件,避免无意义的阻塞等待。如果连接套接字是阻塞的,就相当于在异步模型中插入了同步阻塞的操作,完全违背了epoll高效处理多连接的设计目标——本来应该同时处理多个客户端请求,结果因为一个阻塞IO拖垮整个服务。
内容的提问来源于stack exchange,提问作者David Ranieri

