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. 关于mysql服务突然运行不了的问题-“本地计算机上的mysql服务启动后停止,某些...”

    1.将mysql数据库的安装目录bin文件路径添加到环境的path中,为了让cmd可以直接输入下面的相关命令,不然cd到mysql的bin下也可以 2.cmd输入mysqld --initialize ...

  2. js检测对象是否是数组

    js检测对象是否是数组 可以通过instanceof 方法一. var arr=[] arr instanceof Array   //true var obj={} obj instanceof A ...

  3. 5.1 qbxt 一测 T1

    禁咒检验 (3MB / 2s)[问题描述] 在古老的世界里,有一个神奇的职业叫做魔法师. 魔法师的特点是会魔法,施放魔法需要念咒语. 在古老的世界里,有一个神奇的职业叫做码农.码农的工作是帮助魔法师记 ...

  4. scanf_s获取参数,清空缓冲区,判断是否读取成功

    #include<stdio.h> int main() { ]; ) { printf("Please input:\n"); ); ) { printf(" ...

  5. selenium——操作滚动条

    在自动化测试的过程中,难免会应用到翻页键,但是webdriver提供的方法都是操作当前页面可见的元素,对于未在当前范围展示的翻页键,该如何操作呢? 小编在这里介绍一种方法:使用JavaScript操作 ...

  6. MySQL字符集设定与查询

    一.字符集设定 MySQL数据库允许对服务器.数据库.数据表.数据列级别的字符集作出互不影响的设定. 1.对服务器字符集设定是通过配置文件中选项character-set-server 设置,如 ch ...

  7. NFS共享存储服务部署

    第1章 NFS介绍 1.1 NFS基本概述 NFS(Network File System)网络文件系统 主要功能是通过局域网络让不同的主机系统之间可以共享文件或目录. NFS系统和Windows网络 ...

  8. Images for Journals

    Images for publication Table of Contents 1. Images for publication 1.1. image format : vector image ...

  9. 转载:CentOS7下部署Django项目详细操作步骤

    部署是基于:centos7+nginx+uwsgi+python3+django 之上做的 文章转自:Django中文网        https://www.django.cn/article/sh ...

  10. LeetCode刷题笔记-递归-路径总和

    题目描述: 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和. 说明: 叶子节点是指没有子节点的节点. 示例: 给定如下二叉树,以及目标和 su ...