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机制的更多相关文章

  1. mosquitto在Linux环境下的部署/安装/使用/测试

    mosquitto在Linux环境下的部署 看了有三四天的的源码,(当然没怎么好好看了),突然发现对mosquitto的源码有了一点点感觉,于是在第五天决定在Linux环境下部署mosquitto. ...

  2. Linux环境下发布.net core

    一.安装Linux环境 1. 安装VM虚拟机和操作系统 VM虚拟工具安装的过程详见:http://blog.csdn.net/stpeace/article/details/78598333.直接按照 ...

  3. linux 环境下部署 Asp.Net Core 项目 访问 oralce 数据库

    1.ASP.NET Core 是一个跨平台的高性能开源框架,可以部署到Linux上,那项目部署在Linux上有哪些好处呢? 1.linux硬件需求小,大部分版本免费,成本低. 2.linux的用户管理 ...

  4. 关于ARP攻击的原理以及在Kali Linux环境下的实现

    关于ARP攻击的原理以及在Kali Linux环境下的实现 全文摘要 本文讲述内容分为两部分,前半部分讲述ARP协议及ARP攻击原理,后半部分讲述在Kali Linux环境下如何实现ARP攻击以及AR ...

  5. [原]对Linux环境下任务调度一点认识

    我一直以来有一个误解,那就是在终端运行某个程序时,按下Ctrl + D时我误以为就是杀死了这个进程,今天才知道原来不是.比如我利用libevent在Linux环境下写了一个网络监听程序,当启动程序之后 ...

  6. 【转载】linux环境下tcpdump源代码分析

    linux环境下tcpdump源代码分析 原文时间 2013-10-11 13:13:02  CSDN博客 原文链接  http://blog.csdn.net/han_dawei/article/d ...

  7. linux环境下tcpdump源代码分析

    Linux 环境下tcpdump 源代码分析 韩大卫@吉林师范大学 tcpdump.c 是tcpdump 工具的main.c, 本文旨对tcpdump的框架有简单了解,只展示linux平台使用的一部分 ...

  8. 由一个简单需求到Linux环境下的syslog、unix domain socket

    本文记录了因为一个简单的日志需求,继而对linux环境下syslog.rsyslog.unix domain socket的学习.本文关注使用层面,并不涉及rsyslog的实现原理,感兴趣的读者可以参 ...

  9. Memcached在Linux环境下的使用详解

    一.引言             写有关NoSQL数据库有关的文章已经有一段时间了,可以高兴的说,Redis暂时就算写完了,从安装到数据类型,在到集群,几乎都写到了.如果以后有了心得,再补充吧.然后就 ...

随机推荐

  1. The MySQL server is running with the –secure-file-priv

    show variables like '%secure%'; 将文件导出路径更改为查询到的secure-file-priv路径下 select * from table where column = ...

  2. 错误的语法:"create view必须是批处理中仅有的语句"

    编写脚本提示: 错误的语法:"create view必须是批处理中仅有的语句" FROM sys.views WHERE name = 'v_CS_UserRoleNames' ) ...

  3. openjudge-1664 放苹果

    总时间限制: 1000ms 内存限制: 65536kB 描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. 输 ...

  4. LINUX:关于Redis集群的节点分配

    文章来源:http://www.cnblogs.com/hello-tl/p/7808268.html 根据上述  Redis集群搭建:http://www.cnblogs.com/hello-tl/ ...

  5. 杭电 4004 The Frog's Games 青蛙跳水 (二分法,贪心)

    Description The annual Games in frogs' kingdom started again. The most famous game is the Ironfrog T ...

  6. 【BZOJ 1222】 [HNOI2001] 产品加工(DP)

    Description 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机 ...

  7. UVA - 10410 Tree Reconstruction (根据dfs序和bfs序恢复一颗树)

    题意: 分析: 这题一开始完全没有思路, 一直没有找出规律. 参考了http://www.cnblogs.com/Wade-/p/6358859.html 和 http://www.cnblogs.c ...

  8. Leetcode 309.最佳买卖股票时机含冷冻期

    最佳买卖股票时机含冷冻期 给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格.​ 设计一个算法计算出最大利润.在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 你不 ...

  9. E题

    题目大意: 找到一个最小的l值,使得a到b-l+1中任取一个数开始前进l次,中间包含至少有k个素数,如果找不到,返回-1: 运用素数打表法和2分法便能简单搞定: 题目链接:http://codefor ...

  10. hdu 4421 和poj3678类似二级制操作(2-sat问题)

    /* 题意:还是二进制异或,和poj3678类似 建边和poj3678一样 */ #include<stdio.h> #include<string.h> #include&l ...