在Linux环境下使用TCP的keepalive机制

欢迎进入Linux社区论坛,与200万技术人员互动交流 >>进入

  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);

  }

[1][2]

所有的胜利,与征服自己的胜利比起来,都是微不足道

在Linux环境下使用TCP的keepalive机制

相关文章:

你感兴趣的文章:

标签云: