Linux下对端关闭连接后写socket会触发SIGPIPE信号,默认终止进程;应屏蔽该信号并检查write返回值(0、-1且errno为EPIPE或EAGAIN)来可靠判断连接状态,同时启用SO_KEEPALIVE或心跳机制主动探测。

当对端关闭连接后继续向socket写数据,Linux会默认发送SIGPIPE信号终止进程。避免程序意外退出,关键在于屏蔽或捕获该信号,并配合write返回值判断连接状态。
屏蔽SIGPIPE信号(推荐)
大多数Socket通信场景下,无需让SIGPIPE中断程序流程。在程序启动时调用signal(SIGPIPE, SIG_IGN)即可全局忽略该信号。这样write()在对端关闭后会直接返回-1并置errno为EPIPE,由应用层统一处理错误,逻辑更清晰可控。
捕获SIGPIPE并做自定义响应
若需在断连时触发日志、清理资源或通知其他模块,可注册信号处理器:
- 使用sigaction()而非signal(),避免不可靠语义和自动重置问题
- 处理器中仅做异步安全操作(如写入pipe、设置标志位),避免调用printf/malloc等非异步信号安全函数
- 通常仍需配合write返回值检查,因信号可能延迟到达,不能完全依赖信号时机判断连接状态
必须检查write()返回值
忽略或捕获SIGPIPE只是第一步,真正可靠的连接异常判断依赖于系统调用返回值:
- write()返回0:对端已关闭连接(shutdown(SHUT_WR)或close)
- write()返回-1且errno == EPIPE:对端已关闭,本端仍尝试写入
- write()返回-1且errno == EAGAIN/EWOULDBLOCK:非阻塞socket暂不可写,需等待可写事件
结合SO_KEEPALIVE或应用层心跳维持连接有效性
SIGPIPE只在实际写操作时触发,无法提前发现对端静默断连。对长连接服务,应启用setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)),或实现应用层心跳机制,主动探测连接可用性,避免写操作时才暴露问题。










