linux网路编程--网络超时检测
Posted sucfrperperseverance
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux网路编程--网络超时检测相关的知识,希望对你有一定的参考价值。
网络超时检测(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 <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/time.h> #define N 128 #define err_log(errlog) do{perror(errlog);exit(1);}while(0) int main(int argc, const char *argv[]) { fd_set readfds; int maxfd; int i = 0; char buf[N] = {}; int ret; int sockfd; int acceptfd; struct sockaddr_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; struct timeval 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 <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <errno.h> #define err_log(errlog) do{perror(errlog); exit(1);}while(0) #define N 128 // ./server 192.168.0.196 10000 void handler(int sig) { printf("timeout....\\n"); } int main(int argc, const char *argv[]) { int sockfd; int confd; struct sockaddr_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(struct sockaddr); 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)); struct sigaction 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秒不输入,则可以看到
以上是关于linux网路编程--网络超时检测的主要内容,如果未能解决你的问题,请参考以下文章