对等端优雅关闭后遇TCP错误(如RST),套接字是否仍会标记可读?
关于RST强制断连的检测与处理
在常规阻塞式socket通信中,recv()返回错误或0时我们能及时处理对等端状态,但如果已经收到对等端的关闭通知(recv()返回0),但我方还有未完成的处理任务或待发送数据,此时对方通过RST强制断连,可通过以下方式检测和处理:
套接字状态与错误获取
当对等端发送RST后,套接字会持续被标记为可读状态。此时调用recv()会直接返回-1,通过系统提供的错误接口可获取具体原因:
- Linux/Unix系统:查看
errno,对应错误码为ECONNRESET(连接被重置) - Windows系统:调用
WSAGetLastError(),对应错误码为WSAECONNRESET
多路复用机制的检测方案
使用select()/epoll()/IOCP这类多路复用工具可以有效检测该情况:
- select()/poll():将目标套接字加入读集合,当套接字触发可读事件时,调用
recv()。若返回-1且错误码为连接重置,即可判定对方已强制断连。 - epoll():为套接字注册
EPOLLIN事件,触发后调用recv()获取错误。如果是边缘触发模式,只需一次调用即可捕获错误状态。 - IOCP:Windows环境下,投递的接收操作会在RST到达后完成,返回的状态码会提示连接重置,以此触发后续终止处理逻辑。
待发送数据的处理逻辑
若我方还有待发送的数据,调用send()时也会触发错误:
- 套接字因RST处于错误状态时,
send()会返回-1,错误码同样为连接重置类标识。 - 即使之前
send()操作成功,后续的send()也会因底层检测到连接已重置而失败,可通过捕获该错误终止处理。
HTTP服务器场景实例处理
针对你提到的HTTP客户端发完请求就发RST断连的场景,服务器可按以下流程处理:
- 用多路复用机制监听所有客户端套接字的读/写事件。
- 客户端发送RST后,对应套接字会触发读事件,调用
recv()捕获连接重置错误,立即终止该客户端的请求处理流程并释放相关资源。 - 若服务器正在准备响应数据,后续调用
send()时会触发错误,同样可据此终止处理。
需要注意:不要在recv()返回0后就完全忽略该套接字的状态,尤其是还有待处理任务或待发数据时,应继续通过多路复用监听,直到确认所有操作完成或检测到错误。
内容的提问来源于stack exchange,提问作者Calmarius
相关产品推荐
相关产品推荐

