TCP C/S心搏函数

心搏函数头文件:

#ifndef _HEART_H_
#define _HEART_H_

#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

static int global_interval;
static int global_maxtimes;
static int handle_sockfd;
static int global_times = 0;
static void sig_alarm(int signo) {
    if (send(handle_sockfd," ",1,MSG_OOB) != 1) {
        printf("sig_alarm error: send error %s\n",strerror(errno));
        exit(1);
    }
    if (++global_times > global_maxtimes) {
        printf("the heart was broken\n");
        exit(1);
    }
    alarm(global_maxtimes);
    return;
}

static void sig_urg(int signo) {
    int n;
    char c;
    if ((n = recv(handle_sockfd,&c,1,MSG_OOB)) < 0) {
        if (errno != EINTR) {
            printf("sig_urg error: %s\n",strerror(errno));
            exit(1);
        }
    }
    global_times = 0;
    return;
}
void heart_alive(int sockfd,int interval,int maxtimes) {
    handle_sockfd = sockfd;
    if (interval < 1) {
        global_interval = 1;
    }else {
        global_interval = interval;
    }
    if (maxtimes < 1) {
        global_maxtimes = 1;
    }else {
        global_maxtimes = maxtimes;
    }
    if (signal(SIGURG,sig_urg) == SIG_ERR) {
        printf("heart_alive:signal error %s\n",strerror(errno));
        exit(1);
    }
    if (fcntl(sockfd,F_SETOWN,getpid()) < 0) {
        printf("heart_alive: signal error: %s\n",strerror(errno));
        exit(1);
    }
    if (signal(SIGALRM,sig_alarm) == SIG_ERR) {
        printf("heart_alive signal error: %s\n",strerror(errno));
        exit(1);
    }
    alarm(global_interval);
}
#endif

心搏函数的应用: 服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include "heart.h"

#define BUFSIZE 4096
#define LISTENQ 100
void server_echo(int sockfd) {
    char buf[BUFSIZE];
    ssize_t n;
    heart_alive(sockfd,2,6);
    for (; ;) {
        if ((n = read(sockfd,buf,BUFSIZE)) < 0) {
            if (errno == EINTR) {
                continue;
            }
            printf("read error: %s\n",strerror(errno));
            exit(1);
        }else if (n == 0) {
            break;
        }
        again: if (write(sockfd,buf,n) != n) {
            if (errno == EINTR) {
                goto again;
            }
            printf("write error: %s\n",strerror(errno));
            exit(1);    
        }
    }
}
int main(int argc,char** argv) {
    if (argc != 2) {
        printf("please add or check <services-name>\n");
        exit(1);
    }

    struct addrinfo hints;
    bzero(&hints,sizeof(struct addrinfo));

    hints.ai_flags = AI_PASSIVE;
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    struct addrinfo* results;
    int err;
    if ((err = getaddrinfo(NULL,argv[1],&hints,&results)) != 0) {
        printf("getaddrinfo error: %s\n",gai_strerror(err));
        exit(1);
    }
    struct addrinfo* dummy = results;
    int sockfd;
    for (; dummy != NULL; dummy = dummy->ai_next) {
        if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,dummy->ai_protocol)) < 0) {
            continue;
        }
        if (bind(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
            break;
        }
        close(sockfd);
    }
    if (listen(sockfd,LISTENQ) < 0) {
        printf("listen error: %s\n",strerror(errno));
        exit(1);
    }
    if (dummy == NULL) {
        freeaddrinfo(results);
        printf("all socket failed\n");
        exit(1);
    }
    freeaddrinfo(results);
    int connfd;
    int pid;
    for (; ;) {
        if ((connfd = accept(sockfd,NULL,NULL)) < 0) {
            if (errno != EINTR) {
                printf("accept error: %s\n",strerror(errno));
                exit(1);
            }else {
                continue;
            }
        }
        if ((pid = fork()) < 0) {
            printf("fork error: %s\n",strerror(errno));
            exit(1);
        }else if (pid == 0) {
            close(sockfd);
            server_echo(connfd);
            close(connfd);
            exit(0);
        }
        close(connfd);
    }   
    return 0;
}

客户端:

#include <stdio.h>
#include "heart.h"
#include <netdb.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <netdb.h>

#define BUFSIZE 4096

void client_echo(int sockfd) {
    char buf[BUFSIZE];
    ssize_t n;
    heart_alive(sockfd,2,5);
    while ((n = read(STDIN_FILENO,buf,BUFSIZE)) > 0) {
        if (write(sockfd,buf,n) != n) {
            printf("write error: %s\n",strerror(errno));
            exit(1);
        }
        if ((n = read(sockfd,buf,BUFSIZE)) < 0) {
            printf("read error: %s\n",strerror(errno));
            exit(1);
        }
        if (write(STDOUT_FILENO,buf,n) != n) {
            printf("write error: %s\n",strerror(errno));
            exit(1);
        }
    }
}
int main(int argc,char** argv) {
    if (argc != 3) {
        printf("please add or check <ip-address or host-name> <services-name or port>\n");
        exit(1);
    }

    struct addrinfo hints;
    bzero(&hints,sizeof(struct addrinfo));

    hints.ai_flags = AI_ALL;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    struct addrinfo* results;
    int err;
    if ((err = getaddrinfo(argv[1],argv[2],&hints,&results)) != 0) {
        printf("getaddrinfo error: %s\n",gai_strerror(err));
        exit(1);
    }

    struct addrinfo* dummy = results;
    int sockfd;
    for (; dummy != NULL; dummy = dummy->ai_next) {
        if ((sockfd = socket(dummy->ai_family,dummy->ai_socktype,dummy->ai_protocol)) < 0) {
            continue;
        }
        if (connect(sockfd,dummy->ai_addr,dummy->ai_addrlen) == 0) {
            break;
        }
        close(sockfd);
    }
    if (dummy == NULL) {
        printf("all socket failed\n");
        freeaddrinfo(results);
        exit(1);
    }
    freeaddrinfo(results);  
    client_echo(sockfd);
}

“`
我们可以通过将其中一个进程挂起(Ctr+Z),就可以观察到心跳停止的效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值