(5)tcp keepalive详解

来源:互联网 发布:淘宝的清关资料哪里填 编辑:程序博客网 时间:2024/05/17 07:13

概念

建立一个TCP连接时,同时也就关联了一堆计时器,其中有些计时器就是keepalive程序处理的。当keepalive计时器达到0时,TCP协议层将会发一个keepalive探测包,这个包不包含任何应用层数据且ACK标志位打开。因为TCP/IP协议规定,允许存在重复的ACK包。因此对方节点不需要业务逻辑层做任何keepalive处理,仅仅是从TCP/IP协议层面就能够对这个ACK进行响应,并且会返回一个不包含任何应用层数据的ACK包。如果此方节点收到该响应包,就可以断定连接在整个网络中仍处于活跃状态。

目的

检查死节点

出现场景:
1-操作系统异常或者处理连接的进程异常中断
2-双方连接的网络中断
比如有A和B两方,B方操作系统掉电重启,此时A方根本是不知道连接状态的,只有当A发包到B收到RST包后才知道连接已经结束了。

连接保活

网络中有些网元节点能够处理的连接数量有限,有可能会把长时间不活跃的连接给丢弃掉。比如路由器的路由表处理的连接就是有限的。

设置

系统设置

参数(路径+文件) 描述 默认值 /proc/sys/net/ipv4/tcp_keepalive_time the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe(是和最近的数据包的间隔,而不是和上一个探测包的间隔); after the connection is marked to need keepalive, this counter is not used any further 7200 /proc/sys/net/ipv4/tcp_keepalive_intvl the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime 75 /proc/sys/net/ipv4/tcp_keepalive_probes the number of unacknowledged probes to send before considering the connection dead and notifying the application layer 9

进程设置

如果只需要单独对某个特定的socket进行keepalive设置的话,可以通过setsockopt函数进行。

int setsockopt(int s, int level, int optname,const void *optval, socklen_t optlen)
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepalive, sizeof(keepalive));//keepalive等于0或1setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (void*)&tcp_keepalive_time, sizeof(tcp_keepalive_time));setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void*)&tcp_keepalive_intvl, sizeof(tcp_keepalive_intvl));setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void*)&tcp_keepalive_probes, sizeof(tcp_keepalive_probes)));

样例如下:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>int main(void);int main(){   int s;   int optval;   socklen_t optlen = sizeof(optval);   /* Create the socket */   if((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {      perror("socket()");      exit(EXIT_FAILURE);   }   /* Check the status for the keepalive option */   if(getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {      perror("getsockopt()");      close(s);      exit(EXIT_FAILURE);   }   printf("SO_KEEPALIVE is %s\n", (optval ? "ON" : "OFF"));   /* Set the option active */   optval = 1;   optlen = sizeof(optval);   if(setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {      perror("setsockopt()");      close(s);      exit(EXIT_FAILURE);   }   printf("SO_KEEPALIVE set on socket\n");   /* Check the status again */   if(getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {      perror("getsockopt()");      close(s);      exit(EXIT_FAILURE);   }   printf("SO_KEEPALIVE is %s\n", (optval ? "ON" : "OFF"));   close(s);   exit(EXIT_SUCCESS);}

业务层面的心跳机制

考虑以下场景,用户三次握手成功了,并且TCP连接状态也是活跃的,但是该用户不发送任何的数据包。这种情况也需要根据自己的业务特点设置连接的超时时间。如果不设置,就说明你的业务允许不进行任何业务操作的连接存在。如果有恶意用户只和服务端进行三次握手,那就会占用服务端大量连接资源。如果是自己的客户端,那么可以在开发的客户端里添加心跳包(这个心跳包最好带有你客户端的签名信息,区分恶意客户端)。

原创粉丝点击