KeepAlive并不是默认开启的,
在Linux系统上没有一个全局的选项去开启TCP的KeepAlive。需要开启
KeepAlive的应用必须在TCP的socket中单独开启。Linux Kernel有三个选项影响到KeepAlive的行为:
net.ipv4.tcpkeepaliveintvl = 75
net.ipv4.tcpkeepaliveprobes = 9
net.ipv4.tcpkeepalivetime = 7200
tcpkeepalivetime的单位是秒,表示TCP链接在多少秒之后没有数据报文传输启动探测报文; tcpkeepaliveintvl单位
是也秒,表示前一个探测报文和后一个探测报文之间的时间间隔,tcpkeepaliveprobes表示探测的次数。
TCP socket也有三个选项和内核对应,通过setsockopt系统调用针对单独的socket进行设置:
TCPKEEPCNT: 覆盖 tcpkeepaliveprobes
TCPKEEPIDLE: 覆盖 tcpkeepalivetime
TCPKEEPINTVL: 覆盖 tcpkeepalive_intvl
#cat /proc/sys/net/ipv4/tcp_keepalive_time
#cat /proc/sys/net/ipv4/tcp_keepalive_intvl
#cat /proc/sys/net/ipv4/tcp_keepalive_probes
#echo 1000> /proc/sys/net/ipv4/tcp_keepalive_time
#echo 50> /proc/sys/net/ipv4/tcp_keepalive_intvl
#echo 20> /proc/sys/net/ipv4/tcp_keepalive_probes
setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
http://blog.csdn.net/dongfangyu/article/details/5537781
#include "/usr/include/linux/tcp.h"
#include "/usr/include/linux/socket.h"
//下面代码要求有ACE,如果没有包含ACE,则请把用到的ACE函数改成linux相应的接口
int keepAlive = 1;//设定KeepAlive
int keepIdle = 5;//开始首次KeepAlive探测前的TCP空闭时间
int keepInterval = 5;//两次KeepAlive探测间的时间间隔
int keepCount = 3;//判定断开前的KeepAlive探测次数
if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1)
ACE_TEXT ("(%P|%t) setsockopt SO_KEEPALIVE error!/n")));
if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle)) == -1)
ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPIDLE error!/n")));
if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval)) == -1)
ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPINTVL error!/n")));
if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount)) == -1)
ACE_TEXT ("(%P|%t)setsockopt TCP_KEEPCNT error!/n")));
http://blog.chinaunix.net/uid-26000296-id-3758651.html
http://www.imooo.com/linux/linux-unix/192810.htm
http://bbs.csdn.net/topics/390540670
如果一直在socket上有数据来往就不会触发keepalive,但是如果30秒一直没有数据往来,则keep alive开始工作:
发送探测包,受到响应则认为网络,是好的,结束探测;如果没有相应就每隔1秒发探测包,一共发送3次,3次后仍
没有相应,则发送RST包关闭连接,也就是从网络开始到你的socket能够意识到网络异常,最多花33秒。但是如果没
有设置keep alive,可能你在你的socket(阻塞性)的上面,接收: recv会一直阻塞不能返回,除非对端主动关闭连
#define LENGTH_OF_LISTEN_QUEUE 20
int EstablishServer(struct sockaddr_in * addr,socklen_t addrLen,int port);
void * HeartService(void * arg);
void setnonblocking(int sock);
void socketkeepalive(int sockfd);
struct sockaddr_in server_addr,client_addr;
socklen_t clientLen=sizeof(struct sockaddr);
serverFd=EstablishServer(&server_addr,sizeof(server_addr),SERVER_PORT);
cout<<"serverFd create failed!"<<endl;
if((clientFd=accept(serverFd,(struct sockaddr *)&client_addr,&clientLen))<0)
perror("accept wrong !:");
cout<<"----------------------------------------------------------------"<<endl;
printf("accept from %s:%d",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
int pthrst=pthread_create(&clientTid,NULL,HeartService,(void *)&clientFd);
perror("pthread_create wrong ! :");
int EstablishServer(struct sockaddr_in * addr,socklen_t addrLen,int port)
int listenfd=socket(AF_INET,SOCK_STREAM,0);
perror("listenfd socket error");
addr->sin_family=AF_INET;
addr->sin_addr.s_addr=htonl(INADDR_ANY);
addr->sin_port=htons(port);
if(bind(listenfd,(struct sockaddr *)addr,addrLen)<0)
if(listen(listenfd,LENGTH_OF_LISTEN_QUEUE)<0)
void *HeartService(void * arg)
pthread_t tid=pthread_self();
int clientFd=*(int *)arg;
cout<<"New thread create,the tid is "<<tid<<" the clientFd is "<<clientFd<<endl;
socketkeepalive(clientFd);
if((n=recv(clientFd,buf,MAXBUF,0))<0)
if(errno==ECONNRESET)//表示连接被重置了,已经无效了,关闭它,删除它
printf("It is ECONNRESET:%s",strerror(ECONNRESET));
else if(errno==ETIMEDOUT)
cout<<"Ha Ha you want ETIMEDOUT"<<endl;
perror("read error!"); //其他错误
else if(n==0)//有读事件触发,但是read返回0,所以是对面已经关闭sockfd了