心跳包
来源:互联网 发布:java开发工程师做什么 编辑:程序博客网 时间:2024/04/28 19:16
Socket编程中:心跳包的实现机制
心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在TCP/IP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
心跳包一般来说都是在逻辑层发送空的echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
其实,要判定掉线,只需要send或者recv一下,如果结果为零,则为掉线。但是,在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
int client_fd;
static int flag = 0;
struct sockaddr_in peer_addr;
int addrlen = sizeof(struct sockaddr_in);
void handler_function(int signum)
{
int i = 0;
if(flag == 0)
{
for(i = 0;i < 3;i ++)
{
sendto(client_fd,NULL,0,0,(struct sockaddr *)&peer_addr,addrlen);
usleep(500);
}
alarm(10);
flag = 1;
}else{
printf("The server is closed.\n");
kill(getppid(),SIGKILL);
exit(EXIT_SUCCESS);
}
return;
}
int main(int argc,char *argv[])
{
char buf[100];
signal(SIGALRM,handler_function);
if(argc < 3)
{
fprintf(stderr,"usage : %s ip port.\n",argv[0]);
exit(EXIT_FAILURE);
}
if((client_fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("Fail to socket");
exit(EXIT_FAILURE);
}
bzero(&peer_addr,sizeof(peer_addr));
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons(atoi(argv[2]));
peer_addr.sin_addr.s_addr = inet_addr(argv[1]);
alarm(10);
while(1)
{
sleep(1);
sendto(client_fd,NULL,0,0,(struct sockaddr *)&peer_addr,addrlen);
recvfrom(client_fd,NULL,0,0,NULL,NULL);
alarm(10);
if(flag == 1)
flag = 0;
}
exit(EXIT_FAILURE);
}
心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在TCP/IP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
心跳包一般来说都是在逻辑层发送空的echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
其实,要判定掉线,只需要send或者recv一下,如果结果为零,则为掉线。但是,在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理呀,重新连接呀……当然,这个自然是要由逻辑层根据需求去做了。总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
int client_fd;
static int flag = 0;
struct sockaddr_in peer_addr;
int addrlen = sizeof(struct sockaddr_in);
void handler_function(int signum)
{
int i = 0;
if(flag == 0)
{
for(i = 0;i < 3;i ++)
{
sendto(client_fd,NULL,0,0,(struct sockaddr *)&peer_addr,addrlen);
usleep(500);
}
alarm(10);
flag = 1;
}else{
printf("The server is closed.\n");
kill(getppid(),SIGKILL);
exit(EXIT_SUCCESS);
}
return;
}
int main(int argc,char *argv[])
{
char buf[100];
signal(SIGALRM,handler_function);
if(argc < 3)
{
fprintf(stderr,"usage : %s ip port.\n",argv[0]);
exit(EXIT_FAILURE);
}
if((client_fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)
{
perror("Fail to socket");
exit(EXIT_FAILURE);
}
bzero(&peer_addr,sizeof(peer_addr));
peer_addr.sin_family = AF_INET;
peer_addr.sin_port = htons(atoi(argv[2]));
peer_addr.sin_addr.s_addr = inet_addr(argv[1]);
alarm(10);
while(1)
{
sleep(1);
sendto(client_fd,NULL,0,0,(struct sockaddr *)&peer_addr,addrlen);
recvfrom(client_fd,NULL,0,0,NULL,NULL);
alarm(10);
if(flag == 1)
flag = 0;
}
exit(EXIT_FAILURE);
}
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 心跳包
- 关于心跳包
- JAVA的心跳包
- soket 心跳包
- 心跳包写法
- OpenStack版本升级之Horizon
- SOA 和 EAI概念
- clsoesocket, shutdown
- Linux Platform Device and Driver
- 右键增加cmd here
- 心跳包
- JMeter正则表达式提取器
- 介绍 JetUI
- 获取目录大小和文件个数的工具类
- linux中vmstat命令详解
- Android 颜色大全 colors.xml
- 运用URLClassLoader加载外部jar包的java类,生成Class文件
- Java synchronized
- 稀疏编码/ICA模型---MRF统计结构