在Linux环境下使用TCP的keepalive机制
Linux内置支持keepalive机制,为了使用它,你须要使能TCP/IP网络,为了可以配置内核在执行时的參数。你还须要procfs和sysctl的支持。
这个过程涉及到keepalive使用的三个用户驱使的变量:
tcp_keepalive_time:表示的是近期一次数据包(简单的不含数据的ACKs包)发送与第一次keepalive探针发送之间的时间间隔;当连接被标记为keepalive之后。这个计数器就不会再使用。
tcp_keepalive_intvl:表示的是并发keepalive探针之间的时间间隔。
tcp_keepalive_probes:在确定连接已经断开而且通知应用层之前所发送的没有得到回复的探针数。
对于这三个參数能够在Linux系统的终端中查看和改动它们的缺省值:
查看三个參数的值:
[root@Server3 ~]# cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
[root@Server3 ~]# cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
[root@Server3 ~]# cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
通过命令对这三个參数值进行改动(图中将三个參数值分别设为:600、60、20):
[root@Server3 ~]# echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
[root@Server3 ~]# echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
[root@Server3 ~]# echo 6 > /proc/sys/net/ipv4/tcp_keepalive_probes
这样的方式重置三个參数值,在系统重新启动后三个參数的值又会恢复到默认值,详细怎样让系统永远记住自己设置的值,可參考其它资料,我们如今关系的是怎样在程序中使用keepalive机制并设置这三个參数的值。
在程序中使用keepalive机制
想在程序中使用这样的机制,仅仅须要使用setsockopt()函数。
setsockopt()函数用于随意类型、随意状态套接口的设置选项值。虽然在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。
选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据能否够从套接口发送等等。
以下为setsockopt()函数的原型:
#include <sys/types.h>
#include <sys/socket.h>
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);
參数:
sock:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:须要訪问的选项名。
optval:对于getsockopt()。指向返回选项值的缓冲。对于setsockopt()。指向包括新选项值的缓冲。
optlen:对于getsockopt()。作为入口參数时,选项值的最大长度。作为出口參数时。选项值的实际长度。
对于setsockopt()。现选项的长度。
为了使用函数setsockopt()将某个特定的套接字的keepalive机制打开,參数s是一个socket文件描写叙述符。必需要在这之前使用socket()函数进行创建。參数level必须设置为SOL_SOCKET;第三个參数必须设置为SO_KEEPALIVE。optval參数必须是一个布尔型整型变量,表示想要使能这个选项;最后一个參数表示第四个參数的大小。
程序实现心跳包检測机制
首先要在备份机和源机之间建立一个专门的socket链路来进行心跳检測。
在源机端,在进行数据迁移之前,会建立一个socket来监听备份机的连接。并将这个socket和相应的处理函数放入原软件的io处理列表中。代码例如以下:
int listenfd;
struct sockaddr_in server_sin; /* establish socket */
listenfd=socket(AF_INET,SOCK_STREAM,0);
server_sin.sin_family=AF_INET;
server_sin.sin_addr.s_addr=htonl(INADDR_ANY);
server_sin.sin_port=htons(PORT);
bind(listenfd,(struct sockaddr *)&server_sin,sizeof(server_sin));
/* establish end */ listen(listenfd,1024); qemu_set_fd_handler2(listenfd, NULL, tcpkeepalive_server, NULL,
(void *)(intptr_t)listenfd);
该socket相应的处理函数例如以下:
static void tcpkeepalive_server(void *opaque)
{
int connfd;
struct sockaddr_in client_sin;
socklen_t client_len=sizeof(client_sin);
int listenfd = (intptr_t)opaque; connfd=accept(listenfd,(struct sockaddr *)&client_sin,&client_len);
}
在备份机端,当其開始作为备份机时,会建立socket连接源机的监听端。并设置相应的tcpkeepalive參数。然后将socket和相应的处理函数增加io处理列表。
我们建立的socket是一个心跳检測专用链路。其上不会有数据流动,仅仅有一种情况备份机端会收到数据,那就是源端出现了故障。tcpkeepalive机制会返回一个错误信息,所以捕捉到了这个信息,备份机就会跳转到相应的处理函数,接替源机開始执行。
相应代码例如以下:
int sockfd;
struct sockaddr_in sin; int optval;
socklen_t optlen = sizeof(optval); sockfd=socket(AF_INET,SOCK_STREAM,0);
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=addr.sin_addr.s_addr;
sin.sin_port=htons(PORT); optval = 1;
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); optval = 5;
setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, &optval, optlen); optval = 1;
setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen); optval = 1;
setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen); connect(sockfd,(struct sockaddr *)&sin,sizeof(sin)); qemu_set_fd_handler2(sockfd, NULL, tcpkeepalive_vm_start, NULL,
(void *)(intptr_t)sockfd);
该socket相应的处理函数非常easy,就是让备份机開始执行:
static void tcpkeepalive_vm_start(void *opaque)
{
vm_start();
}
在Linux环境下使用TCP的keepalive机制的更多相关文章
- mosquitto在Linux环境下的部署/安装/使用/测试
mosquitto在Linux环境下的部署 看了有三四天的的源码,(当然没怎么好好看了),突然发现对mosquitto的源码有了一点点感觉,于是在第五天决定在Linux环境下部署mosquitto. ...
- Linux环境下发布.net core
一.安装Linux环境 1. 安装VM虚拟机和操作系统 VM虚拟工具安装的过程详见:http://blog.csdn.net/stpeace/article/details/78598333.直接按照 ...
- linux 环境下部署 Asp.Net Core 项目 访问 oralce 数据库
1.ASP.NET Core 是一个跨平台的高性能开源框架,可以部署到Linux上,那项目部署在Linux上有哪些好处呢? 1.linux硬件需求小,大部分版本免费,成本低. 2.linux的用户管理 ...
- 关于ARP攻击的原理以及在Kali Linux环境下的实现
关于ARP攻击的原理以及在Kali Linux环境下的实现 全文摘要 本文讲述内容分为两部分,前半部分讲述ARP协议及ARP攻击原理,后半部分讲述在Kali Linux环境下如何实现ARP攻击以及AR ...
- [原]对Linux环境下任务调度一点认识
我一直以来有一个误解,那就是在终端运行某个程序时,按下Ctrl + D时我误以为就是杀死了这个进程,今天才知道原来不是.比如我利用libevent在Linux环境下写了一个网络监听程序,当启动程序之后 ...
- 【转载】linux环境下tcpdump源代码分析
linux环境下tcpdump源代码分析 原文时间 2013-10-11 13:13:02 CSDN博客 原文链接 http://blog.csdn.net/han_dawei/article/d ...
- linux环境下tcpdump源代码分析
Linux 环境下tcpdump 源代码分析 韩大卫@吉林师范大学 tcpdump.c 是tcpdump 工具的main.c, 本文旨对tcpdump的框架有简单了解,只展示linux平台使用的一部分 ...
- 由一个简单需求到Linux环境下的syslog、unix domain socket
本文记录了因为一个简单的日志需求,继而对linux环境下syslog.rsyslog.unix domain socket的学习.本文关注使用层面,并不涉及rsyslog的实现原理,感兴趣的读者可以参 ...
- Memcached在Linux环境下的使用详解
一.引言 写有关NoSQL数据库有关的文章已经有一段时间了,可以高兴的说,Redis暂时就算写完了,从安装到数据类型,在到集群,几乎都写到了.如果以后有了心得,再补充吧.然后就 ...
随机推荐
- 已安全化的ActiveX控件卸载时出现"DllUnregisterServer函数出错,错误代码:0x80070002"问题解决
已安全化的ActiveX控件卸载时出现"DllUnregisterServer函数出错,错误代码:0x80070002"问题解决 情况一:当该控件未注册或者已经卸载时,你尝试卸 ...
- sleep 和wait的差别
基本的差别 1.sleep 是Thread 类的方法,wait 是Object类中定义的方法 2.sleep()方法可以在任何地方使用 3.wait()方法只能在synchronized方法中使用,或 ...
- spring中注解的实现原理
@Autowired和@Resource的区别: 在Java中使用@Autowired和@Resource注解进行装配,这两个注解分别是:1.@Autowired按照默认类型(类名称)装配依赖对象,默 ...
- redis:安装配置主从
1.安装依赖包 yum install gcc gcc-c++ -y 2.下载安装包,解压 cd /usr/local/src/wget http://download.redis.io/releas ...
- Android 图片设置圆角 方法之二
Android中经常会遇到对图片进行二次处理,例如加圆角,或者显示圆形图片.接下来我们再介绍一种方法. 首先, 自定义ImageView: android:id="@+id/iv" ...
- 【Codeforces 1083A】The Fair Nut and the Best Path
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 我们最后要的是一条最长的路径. 这条路径的权值和是所有点的权值和-所有边的权值和且这个值最大. 显然如果我们在某一条边上的累计的权值和< ...
- 关于面试总结-python笔试题(递归)
前言 本篇继续收集一些常见的python笔试题,以基础知识为主,递归是面试最喜欢考的一个问题,不管是做开发还是测试,都无法避免考递归.本篇结合实际案例,讲下几种关于递归的场景. 计算n的阶乘 计算n! ...
- Leetcode 235.二叉搜索树的公共祖先
二叉搜索树的公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 ...
- Android ScaleDrawable
顾名思义,Android ScaleDrawable实现一个drawable的缩放.写一个例子. 一个线性布局,垂直放几个ImageView,然后依次缩放若干个ScaleDrawable. 布局文件: ...
- Excel数据导入Sql Server出现Null(转)
Excel文件: 序号 姓名 内部电话 住址 1 小李 1234 …… 2 小王 5678 …… 3 小张 2345(国内长途) …… …… …… …… …… 如上结构的Excel文件,用SQL Se ...