重连失败时需通过connect()返回值和errno区分网络断开与服务端宕机:返回-1且errno为einprogress(非阻塞)、econnrefused、etimedout或ehostunreach,表明服务端不可达;连接成功后read()返回0或-1且errno为econnreset/enotconn,则大概率服务端已关闭或宕机。

重连失败时如何判断是网络断开还是服务端宕机
关键看 connect() 返回值和 errno:返回 -1 且 errno 是 EINPROGRESS(非阻塞模式)或 ECONNREFUSED、ETIMEDOUT、EHOSTUNREACH,基本可判定服务端不可达;若连接成功后读写时触发 read() 返回 0 或 -1 且 errno == ECONNRESET 或 ENOTCONN,大概率是服务端已关闭连接或宕机。
注意:EAGAIN 或 EWOULDBLOCK 在非阻塞模式下只是暂时无响应,不表示失败,不能直接进重连流程。
- 建议每次
connect()前先close()当前 socket,避免残留状态干扰 - 不要仅靠心跳超时就断定服务端挂了——可能只是网络抖动,需结合多次读失败 + 连接重建失败综合判断
-
getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len)可用于非阻塞 connect 后检查真实错误码,比只看errno更可靠
重连间隔该设成固定值还是指数退避
固定间隔(如 1s)在服务端短时重启时响应快,但会加剧服务端压力;指数退避(如 1s → 2s → 4s → 8s,上限建议 30s)能有效抑制雪崩式重连请求,更适合生产环境。
实际中推荐从 1s 开始,每次失败翻倍,达到 30s 后不再增长,并加入小范围随机抖动(±300ms),防止集群内大量客户端同步重试。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
usleep(1000000 * delay_sec + rand() % 300000)实现抖动,避免sleep()精度太粗 - 记录连续失败次数,超过阈值(如 10 次)可降级为仅本地保活或通知上层,而非盲目重试
- 若使用
epoll或select,重连定时器应统一由事件循环驱动,别用独立线程 sleep,否则难以响应中断信号
重连过程中如何安全地处理未发送完的数据
不能丢弃,也不能盲目重发。正确做法是把待发数据缓存在内存队列(如 std::queue<:vector>></:vector>),重连成功后再逐条尝试 send();若 send() 返回部分长度(比如只发了前 100 字节),需保存偏移并继续发剩余部分。
- 每条消息建议加简单序列号或时间戳,服务端可做幂等去重,避免网络重复导致业务错乱
- 缓存大小要设上限(如 1MB),超限时可丢弃最老消息并记录 warning,防止 OOM
- 重连期间新产生的消息仍可入队,但需检查缓存是否已满,满则按策略丢弃或阻塞(视业务容忍度而定)
如何避免重连逻辑被阻塞导致整个客户端卡死
核心是把 connect() 设为非阻塞模式,并用 select() 或 poll() 等待可写事件(而非直接循环 retry),否则单次超时可能卡住几百毫秒甚至几秒。
示例关键片段:
int sock = socket(AF_INET, SOCK_STREAM, 0);
int flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
// ... 设置 addr ...
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1 && errno != EINPROGRESS) {
close(sock); return;
}
// 然后用 poll() 等待 POLLOUT,再 check SO_ERROR
- 别在主线程里 while(1) sleep+connect,这会让整个程序失去响应能力
- 如果用多线程,重连任务必须与业务收发线程解耦,共享 socket fd 要加锁,但更推荐每个连接独占 fd
- Linux 下可考虑
SO_KEEPALIVE辅助探测,但它默认 2 小时才生效,不能替代主动重连逻辑
重连不是“连上了就行”,真正难的是状态同步、数据一致性、以及不让重连本身变成 DoS 工具——这些细节比写个 while 循环重要得多。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










