心搏函数头文件:
#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),就可以观察到心跳停止的效果