网络超时检测(1)
设置socket的属性SO_RCVTIMEO
参考代码:
struct timeval tv;
tv..tv_sec=5;//设置5s时间
tv.tv_usec=0;
setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));//设置接收超时
recv/recvfrom
网络超时检查(2)
用select检测socket是否‘ready’
参考代码:
struct fd_set rdfds;
struct timeval tv={5,0};
FD_ZERO(&rdfds);
FD_SET(sockfd,&rdfds);
if(selecet(sockfd+1,&rdfs,NULL,NULL,&tv)>0)//socket准备就绪
{
recv/recvfrom
}
selct-timeout.c
#include #include#include#include#include#include#include#include#include
#define N 128
#define err_log(errlog) do{perror(errlog);exit(1);}while(0)
int main(int argc, const char *argv[])
{
fd_set readfds;intmaxfd;int i = 0;char buf[N] ={};intret;intsockfd;intacceptfd;structsockaddr_in serveraddr, clientaddr;
socklen_t addrlen= sizeof(clientaddr);if(argc < 3)
{
fprintf(stderr,"Usage:%s serverip port.\n", argv[0]);
}if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
err_log("fail to socket");
}
serveraddr.sin_family=AF_INET;
serveraddr.sin_addr.s_addr= inet_addr(argv[1]);
serveraddr.sin_port= htons(atoi(argv[2]));if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
err_log("fail to bind");
}if(listen(sockfd, 5) < 0)
{
err_log("fail to listen");
}
FD_ZERO(&readfds);
maxfd=sockfd;structtimeval tv;while(1)
{
FD_SET(0, &readfds);
FD_SET(sockfd,&readfds);
tv.tv_sec= 5;
tv.tv_usec= 0;if((ret = select(maxfd+1,&readfds, NULL, NULL,&tv)) < 0)
{
err_log("fail to select");
}
printf("After select.\n");switch(ret)
{case 0:
printf("Timeout....\n");break;default:for(i = 0; i < maxfd+1; i++)
{if(FD_ISSET(i, &readfds))
{if(i == 0)
{
fgets(buf, N, stdin);
printf("buf:%s", buf);
}if(i ==sockfd)
{if((acceptfd = accept(sockfd, (struct sockaddr*)&clientaddr, &addrlen)) < 0)
{
err_log("fail to accept");
}
printf("%s --> %d --> acceptfd = %d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), acceptfd);
}
}
}//end default
} //endswitch
}return 0;
}
网络超时(3)
设置定时器(timer),捕捉SIGALRM信号
参考代码:
void handler(int signo){return;}
//一旦进程收到这个信号,执行完信号处理函数之后,下一个函数就会直接返回,不阻塞在哪里
struct sigaction act;
sigaction(SIGALRM,NULL,&act);
act.sa_handler=handler
act.sa_flag&=~SA_RESTART;
sigaction(SIGALRM,&act,NULL);
alarm(5)
if(recv(...)<0)....
server-alarm.c
#include #include#include#include#include#include#include#include#include
#define err_log(errlog) do{perror(errlog); exit(1);}while(0)
#define N 128
//./server 192.168.0.196 10000
void handler(intsig)
{
printf("timeout....\n");
}int main(int argc, const char *argv[])
{intsockfd;intconfd;structsockaddr_in serveraddr, clientaddr;char buf[N] ={};if(argc != 3)
{
fprintf(stderr,"Usage:%s serverip port.\n", argv[0]);return -1;
}if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
err_log("fail to socket");
}
printf("sockfd = %d\n", sockfd);
serveraddr.sin_family=AF_INET;
serveraddr.sin_addr.s_addr= inet_addr(argv[1]);
serveraddr.sin_port= htons(atoi(argv[2]));if(bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
{
err_log("fail to bind");
}if(listen(sockfd, 10) < 0)
{
err_log("fail to listen");
}
socklen_t addrlen= sizeof(structsockaddr);if((confd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen)) < 0)
{
err_log("fail to accept");
}
printf("confd = %d , %s --> %d \n", confd , inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));structsigaction act;
sigaction(SIGALRM, NULL,&act);
act.sa_handler=handler;
act.sa_flags&= ~SA_RESTART;
sigaction(SIGALRM,&act, NULL);while(1)
{
alarm(5);if(recv(confd, buf, N, 0) < 0)
{if(errno == 4)
{
printf("errno = %d\n", errno);
}else{
err_log("fail to recv");
}
}
printf("From client:%s\n", buf);
}
close(sockfd);return 0;
}
编译运行,如果客户端5秒不输入,则可以看到