Linux系统下的设置TCP心跳机制Keepalive为什么总是无效果
最近在Linux系统下的研究心跳包机制,遍了一个简单的在服务器端测试客户端连接的例子,具体内容是客户端在for循环里发送字符串给服务器端,服务端接收后,再将字符串发送给客户端,由客户端显示出来。可不知怎么的拔掉网线后,没有效果。再插上网线后程序有时候继续运行,求这方面的高手解答帮忙。
服务端代码如下:
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<sys/socket.h>
#include<sys/epoll.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<errno.h>
#include<unistd.h>
#include<string.h>
#include<netinet/tcp.h>
#define SERVER_PORT 3333
#define LENGTH_OF_LISTEN_QUEUE 20
#define MAXBUF 200
using namespace std;
int EstablishServer(struct sockaddr_in * addr,socklen_t addrLen,int port);
void * HeartService(void * arg);
void setnonblocking(int sock);
void socketkeepalive(int sockfd);
int main()
{
struct sockaddr_in server_addr,client_addr;
int serverFd,clientFd;
socklen_t clientLen=sizeof(struct sockaddr);
//建立socket连接
serverFd=EstablishServer(&server_addr,sizeof(server_addr),SERVER_PORT);
if(serverFd==-1)
{
cout<<"serverFd create failed!"<<endl;
exit(1);
}
for(;;)
{
//等待连接的请求
if((clientFd=accept(serverFd,(struct sockaddr *)&client_addr,&clientLen))<0)
{
perror("accept wrong !:");
exit(1);
}
cout<<"----------------------------"<<endl;
printf("accept from %s:%d\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
pthread_t clientTid;
int pthrst=pthread_create(&clientTid,NULL,HeartService,(void *)&clientFd);
if(pthrst!=0)
{
perror("pthread_create wrong ! :");
}
}
return 0;
}
//建立服务端socket的通信,绑定端口
int EstablishServer(struct sockaddr_in * addr,socklen_t addrLen,int port)
{
int listenfd=socket(AF_INET,SOCK_STREAM,0);
if(listenfd<0)
{
perror("listenfd socket error");
return -1;
}
bzero(addr,addrLen);
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)
{
perror("bind error");
return -1;
}
if(listen(listenfd,LENGTH_OF_LISTEN_QUEUE)<0)
{
perror("listen error");
return -1;
}
return listenfd;
}
//心跳机制线程
void *HeartService(void * arg)
{
//获得自身的线程号
pthread_t tid=pthread_self();
//获得传送过来的clientFd
int clientFd=*(int *)arg;
cout<<"New thread create,the tid is "<<tid<<" the clientFd is "<<clientFd<<endl;
char buf[MAXBUF];
int n,m,count=0;
socketkeepalive(clientFd);
for(;;)
{
if((n=recv(clientFd,buf,MAXBUF,0))<0)
{
if(errno==ECONNRESET)//表示连接被重置了,已经无效了,关闭它,删除它
{
printf("It is ECONNRESET:%s\n",strerror(ECONNRESET));
close(clientFd);
}
else if(errno==ETIMEDOUT)
{
cout<<"Ha Ha you want ETIMEDOUT"<<endl;
close(clientFd);
}
else
{
perror("read error!"); //其他错误
close(clientFd);
exit(1);
}
}
else if(n==0)//有读事件触发,但是read返回0,所以是对面已经关闭sockfd了
{
cout<<"n=0 ,clientFd is "<<clientFd<<" and tid is "<<tid<<endl;
close(clientFd);
}
else
{
buf[n]='\0';
cout<<"1: received success,buf: "<<buf<<endl;
}
m=strlen(buf);
if(write(clientFd,buf,m)<0)
{
cout<<"write wrong ! and sockfd is:"<<clientFd<<endl;
}
else
{
cout<<"2: send success,buf: "<<buf<<endl;
}
}
}
void socketkeepalive(int sockfd)
{
int keepAlive=1;//开启keepalive属性
int keepIdle=3;//如该连接在5秒内没有任何数据往来,则进行探测
int keepInterval=2;//探测时发包的时间间隔为2秒
int keepCount=3;//探测尝试的次数。如果第1次探测包就收到响应了,则后2次的不再发送
if(setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,(void *)&keepAlive,sizeof(keepAlive))!=0)//若无错误发生,setsockopt()返回值为0
{
cout<<"It is SO_KEEPALIVE WRONG!"<<endl;
exit(1);
}
if(setsockopt(sockfd,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle))!=0)
{
cout<<"It is TCP_KEEPIDLE WRONG!"<<endl;
exit(1);
}
if(setsockopt(sockfd,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval))!=0)
{
cout<<"It is TCP_KEEPIDLE WRONG!"<<endl;
exit(1);
}
if(setsockopt(sockfd,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount))!=0)
{
cout<<"It is TCP_KEEPCNT WRONG!"<<endl;
exit(1);
}
}
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/epoll.h>
#include<netinet/in.h>
#include<string.h>
#include<netdb.h>
#include<unistd.h>
#include<time.h>
#include<errno.h>
#include<fcntl.h>
#include<netinet/tcp.h>
#include<string.h>
#define SERVPORT 3333
#define MAXDATASIZE 200
using namespace std;
void sockfdalive(int sockfd);
void setnonblocking(int sock);
int main(int argc,char *argv[]){
int sockfd,recvbytes;
struct hostent *host;
struct sockaddr_in serv_addr;
char str[MAXDATASIZE];
char tempbuf[MAXDATASIZE];
char num[12];
int lenstr;
int srcount=0;
if(argc<2){
fprintf(stderr,"Please enter the server's hostname!\n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL)
{
herror("gethostbyname wrong !");
exit(1);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket create wrong !");
exit(1);
}
bzero(&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr=*((struct in_addr *)host->h_addr);
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
perror("connect wrong !");
exit(1);
}
sockfdalive(sockfd);//设置保活机制
for(;;)
{
//sleep(1);
srcount++;
sprintf(tempbuf,"Hello heartactive! %d",srcount);
lenstr=strlen(tempbuf);
if(send(sockfd,tempbuf,lenstr,0)==-1)//发送
{
perror("send wrong !");
exit(1);
}
cout<<"1 send: "<<tempbuf<<endl;
recvbytes=recv(sockfd,str,MAXDATASIZE,0);//接收
if(recvbytes<0)
{
if(errno==ECONNRESET)
{
printf("It is ECONNRESET:%s\n",strerror(ECONNRESET));
exit(1);
}
else if(errno==ETIMEDOUT)
{
cout<<"HAHA client is ETIMEDOUT!"<<endl;
exit(1);
}
else
{
perror("recv wrong !");
exit(1);
}
}
else if(recvbytes==0)
{
cout<<"recvbytes=0"<<endl;
exit(1);
}
else
{
str[recvbytes]='\0';
cout<<"2 received: "<<str<<endl;
}
}
close(sockfd);
}
void sockfdalive(int sockfd){
int keepAlive=1;
int keepIdle=3;
int keepInterval=2;
int keepCount=3;
if(setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,(void *)&keepAlive,sizeof(keepAlive))!=0)
{
cout<<"It is SO_KEEPALIVE WRONG!"<<endl;
exit(1);
}
if(setsockopt(sockfd,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle))!=0)
{
cout<<"It is TCP_KEEPIDLE WRONG!"<<endl;
exit(1);
}
if(setsockopt(sockfd,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval))!=0)
{
cout<<"It is TCP_KEEPIDLE WRONG!"<<endl;
exit(1);
}
if(setsockopt(sockfd,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount))!=0)
{
cout<<"It is TCP_KEEPCNT WRONG!"<<endl;
exit(1);
}
}
看看这个
http://blog.csdn.net/ctthuangcheng/article/details/8596818
[解决办法]