You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C/C++服务端无返回时客户端如何快速检测socket/以太网连接断开

客户端TCP连接实时检测解决方案

问题根因

  • 仅服务端开启了TCP keepalive,客户端未开启对应配置,无法主动感知链路断开、服务端进程异常退出、网线拔掉等故障
  • TCP原生send接口只要内核socket缓冲区尚有剩余空间就会返回成功,哪怕连接已经处于半开状态,仅判断send返回值无法及时识别断连
  • 现有客户端无任何连接存活检测逻辑,断连后仍会持续向无效socket写入数据,导致业务数据丢失

修复方案

我们直接复用现有服务端的TCP keepalive机制,仅修改客户端即可实现秒级断连检测,无需改动服务端逻辑:

  1. 客户端连接成功后,为socket开启TCP keepalive,配置和服务端对齐的探测参数:
    • 10秒无交互就发起探测
    • 连续2次探测失败就判定连接断开
    • 探测报文间隔2秒
      总检测耗时最多14秒,可根据业务需要调整参数实现更快的检测速度
  2. 增加send返回值的错误判断,检测到断连后直接退出业务逻辑,关闭socket,避免无效写入

修正后客户端代码

#include<stdio.h>
#include<string.h>  
#include<sys/socket.h>
#include<arpa/inet.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include<iostream>
#include <errno.h>

int main(int argc , char *argv[])
{
    int socket_desc;
    struct sockaddr_in server;
    char *message;

    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
        return -1;
    }

    server.sin_addr.s_addr = inet_addr("192.168.4.28");
    server.sin_family = AF_INET;
    server.sin_port = htons( 6000 );

    if (connect(socket_desc , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        puts("connect error");
        close(socket_desc);
        return 1;
    }

    // 新增:客户端开启TCP keepalive配置
    int flags = 1;
    if (setsockopt(socket_desc, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags))) { 
        perror("ERROR: setsocketopt(), SO_KEEPALIVE"); 
        close(socket_desc);
        return -1; 
    };

    flags = 10;
    if (setsockopt(socket_desc, SOL_TCP, TCP_KEEPIDLE, (void *)&flags, sizeof(flags))) { 
        perror("ERROR: setsocketopt(), TCP_KEEPIDLE"); 
        close(socket_desc);
        return -1; 
    };

    flags = 2;
    if (setsockopt(socket_desc, SOL_TCP, TCP_KEEPCNT, (void *)&flags, sizeof(flags))) { 
        perror("ERROR: setsocketopt(), TCP_KEEPCNT"); 
        close(socket_desc);
        return -1; 
    };

    flags = 2;
    if (setsockopt(socket_desc, SOL_TCP, TCP_KEEPINTVL, (void *)&flags, sizeof(flags))) { 
        perror("ERROR: setsocketopt(), TCP_KEEPINTVL"); 
        close(socket_desc);
        return -1; 
    };

    puts("Connected\n");
    message = "test";

    for(int i = 1; i < 10000; i++)
    {
        sleep(1);
        //Send some data
        ssize_t send_ret = send(socket_desc , message , strlen(message) , 0);
        if( send_ret < 0)
        {
            printf("Send failed, errno:%d, error info:%s, connection broken, exit\n", errno, strerror(errno));
            break;
        }
        std::cout << i << ". test data send" << std::endl;
    }

    close(socket_desc);
    return 0;
}

验证说明

修改后拔掉网线或者直接杀服务端进程,客户端会在最多14秒内检测到连接异常,退出发送循环,不会再继续写入无效数据。如果需要更快的检测速度,可以调整TCP_KEEPIDLE、TCP_KEEPCNT、TCP_KEEPINTVL三个参数,比如设置为2s空闲、3次探测、1s间隔,最快5秒即可识别断连。

内容的提问来源于stack exchange,提问作者tryingBetter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 09:57:01