简单的心搏函数

本文介绍了一种通过TCP紧急模式实现的心搏机制,用于检测网络连接的健康状态。该机制允许客户端和服务端每秒轮询一次对方,如果连续五秒未收到回应,则认为连接已断开。文章还提供了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

心搏函数
    目的是可以发现对端主机或到对端的通信路径的过早失效

在考虑使用心搏函数前, 可能会先考虑到TCP自带的保活特性, 即SO_KEEPALIVE套接字选项. 然而TCP默认需要在闲置2小时后才发送一个保持存活探测段. 意识到如此后, 接下来可能会想着能不能修改这个参数, 使TCP更早的检测失效. 答案是可行的, 大多系统都支持修改此参数. 但是这些参数通常是按照内核而不是按照每个套接字维护的. 因此改动他们将影响所有开启该选项的套接字.
其次, 两个端系统之间短暂的连接丢失并非总是坏事. TCP一开始就设计成能够对付临时断连, Berkeley的TCP实现将重传8~10分钟才放弃某连接
因此开发人员必须审查想要引入心博机制的具体应用, 确定在没有对端应答的持续时间超过5-10秒后终止连接是好事还是坏事, 不过这种功能大多是不需要的

接下来, 我们将使用TCP的紧急模式周期的轮询对端: 下面, 我们假设每1秒轮询一次, 若持续5秒钟没有听到对端应答则认为对端已经不再存活, 当然这些值可以由应用程序改动
                    

//客户端
#include "unp.h"

static int servfd;
static int nsec;                //客户发送探测带外数据的间隔(秒)
static int maxnprobes;                //达到maxnprobes次未响应, 则判定断开
static int nprobes;                //当前有nprobes次未响应
static void sig_urg(int), sig_alrm(int);    //对于客户来说, sig_alrm函数用来发送探测数据

void heart_beat_cli(int sfd, int sec, int maxp){
    servfd = sfd;
    if((nsec = sec) < 1)
        nsec = 1;
    if((maxnprobes = maxp) < nsec)
        maxnprobes = nsec;
    nprobes = 0;

    signal(SIGURG, sig_urg);
    //设置SIGURG信号的接收进程
    fcntl(servfd, F_SETOWN, getpid());

    signal(SIGALRM, sig_alrm);
    alarm(nsec);
}

//在带外数据来时接收它
static void sig_urg(int s){
    int n;
    char c;

    if((n = recv(servfd, &c, 1, MSG_OOB)) < 0){
        perror("recv error");
        exit(-1);
    }

    nprobes = 0;
}

static void sig_alrm(int s){
    if(++nprobes > maxnprobes){
        fprintf(stderr, "server is missing...\n");
        exit(-1);
    }

    send(servfd, "0", 1, MSG_OOB);
    alarm(nsec);
}


---------------------------------------------------------------------------------------------------------------------------------------------------------------
//服务端
#include "unp.h"

static int clifd;
static int nsec;                //服务器接收探测带外数据的间隔(秒)
static int maxnprobes;                //达到maxnprobes次未响应, 则判定断开
static int nprobes;                //当前有nprobes次未响应
static void sig_urg(int), sig_alrm(int);    //对于服务器来说, sig_alrm函数用来增加nprobes的, 每接收一次带外数据则nprobes减少

void heart_beat_serv(int cfd, int sec, int maxp){
    clifd = cfd;
    if((nsec = sec) < 1)
        nsec = 1;
    if((maxnprobes = maxp) < nsec)
        maxnprobes = nsec;
    nprobes = 0;

    signal(SIGURG, sig_urg);
    //设置SIGURG信号的接收进程
    fcntl(clifd, F_SETOWN, getpid());

    signal(SIGALRM, sig_alrm);
    alarm(nsec);
}

//在带外数据来时接收它
static void sig_urg(int s){
    int n;
    char c;

    if((n = recv(clifd, &c, 1, MSG_OOB)) < 0){
        perror("recv error");
        exit(-1);
    }

    nprobes = 0;
    send(clifd, "1", 1, MSG_OOB);
}

static void sig_alrm(int s){
    if(++nprobes > maxnprobes){
        fprintf(stderr, "server is missing...\n");
        exit(-1);
    }

    alarm(nsec);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值