Select模式和超时
Posted 长风破浪会有时,直挂云帆济沧海
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Select模式和超时相关的知识,希望对你有一定的参考价值。
1 fd_set rset; 2 FD_ZERO(&rset); 3 4 int nready; 5 int maxfd; 6 int fd_stdin = fileno(stdin); 7 if(fd_stdin > sock) 8 { 9 maxfd = fd_stdin; 10 } 11 else 12 { 13 maxfd = sock; 14 } 15 16 char sendbuf[1024] = { 0 }; 17 char recvbuf[1024] = { 0 }; 18 while(1) 19 { 20 FD_SET(fd_stdin,&rset); 21 FD_SET(sock,&rset); 22 nready = select(maxfd+1,&rset,NULL,NULL,NULL); 23 if(nready == -1) 24 ERR_EXIT("select"); 25 if(nready == 0) 26 continue; 27 28 if(FD_ISSET(sock,&rset)) 29 { 30 31 int ret = readline(sock,recvbuf,sizeof(sendbuf)); 32 if(ret == -1) 33 ERR_EXIT("readn"); 34 else if(ret == 0) 35 { 36 printf("server close"); 37 break; 38 } 39 40 fputs(recvbuf,stdout); 41 memset(sendbuf,0, sizeof(sendbuf)); 42 memset(recvbuf,0, sizeof(recvbuf)); 43 } 44 45 if(FD_ISSET(fd_stdin,&rset)) 46 { 47 if(fgets(sendbuf,sizeof(sendbuf),stdin) == NULL) 48 break; 49 writen(sock,sendbuf,strlen(sendbuf)); 50 } 51 } 52 close(sock);
- void FD_CLR(int fd,fd_set *set);
- int FD_ISSET(int fd,fd_set *set);
- void FD_SET(int fd,fd_set *set);
- void FD_ZERO(fd_set *set);
- select的超时
-
1 //读超时 2 int read_timeout(int fd,unsigned int wait_seconds) 3 { 4 int ret = 0; 5 if(wait_seconds > 0) 6 { 7 fd_set read_fdset; 8 struct timeval timeout; 9 10 FD_ZERO(&read_fdset); 11 FD_SET(fd,&read_fdset); 12 13 timeout.tv_sec = wait_seconds; 14 timeout.tv_usec = 0; 15 do 16 { 17 ret = select(fd+1,&read_fdset,NULL,NULL,&timeout); 18 }while(ret < 0 && errno == EINTR) 19 20 if(ret == 0) 21 { 22 ret = -1; 23 errno = ETIMEDOUT; 24 } 25 else if(ret == 1) 26 ret = 0; 27 } 28 return ret; 29 } 30 31 32 //接收超时 33 int accept_timeout(int fd,struct sockaddr_in *addr,unsigned int wait_seconds) 34 { 35 int ret; 36 socklen_t addrlen = sizeof(struct sockaddr_in); 37 38 if(wait_seconds > 0) 39 { 40 fd_set accept_fdset; 41 struct timeval timeout; 42 FD_ZERO(&accept_fdset); 43 FD_SET(fd,&accept_fdset); 44 timeout.tv_sec = wait_seconds; 45 timeout.tv_usec = 0; 46 do 47 { 48 ret = select(fd+1,&accept_fdset,NULL,NULL,&timeout); 49 }while(ret < 0 && errno == EINTR) 50 51 if(ret == -1) 52 return -1; 53 else if(ret == 0) 54 { 55 errno = ETIMEDOUT; 56 return -1; 57 } 58 } 59 if(addr != NULL) 60 ret = accept(fd,(struct sockaddr*)addr,&addrlen); 61 else 62 ret = accept(fd,NULL,NULL); 63 if(ret == -1) 64 ERR_EXIT("accept"); 65 return ret; 66 } 67 68 void activate_nonblock(int fd) 69 { 70 int ret; 71 int flags = fcntl(fd,F_GETFL); 72 if(flags == -1) 73 ERR_EXIT("fcntl"); 74 flags |= O_NONBLOCK; 75 ret = fcntl(fd,F_SETFL,flags); 76 if(ret == -1) 77 ERR_EXIT("fcntl"); 78 } 79 80 void deactivate_nonblock(int fd) 81 { 82 int ret; 83 int flags = fcntl(fd,F_GETFL); 84 if(flags == -1) 85 ERR_EXIT("fcntl"); 86 flags &~ O_NONBLOCK; 87 ret = fcntl(fd,F_SETFL,flags); 88 if(ret == -1) 89 ERR_EXIT("fcntl"); 90 } 91 92 //连接超时 93 int connect_timeout(int fd,struct sockaddr_in *addr, unsigned int wait_seconds) 94 { 95 int ret; 96 socklen_t addrlen = sizeof(struct sockaddr_in); 97 98 if(wait_seconds > 0) 99 activat_nonblock(fd); 100 101 ret = connect(fd,(struct sockaddr*)addr,addrlen); 102 if(ret < 0 && errno == EINPROGRESS) 103 { 104 fd_set connect_fdset; 105 struct timeval timeout; 106 FD_ZERO(&connect_fdset); 107 FD_SET(fd,&connect_fdset); 108 timeout.tv_sec = wait_seconds; 109 timeout.tv_usec = 0; 110 do 111 { 112 ret = select(fd+1,NULL,&connect_fdset,NULL,&timeout); 113 }while(ret < 0 && errno == EINTR) 114 if(ret == 0) 115 { 116 ret = -1; 117 errno = ETIMEDOUT; 118 } 119 else if(ret < 0) 120 return -1; 121 else if(ret == 1) 122 { 123 int err; 124 socklen_t socklen = sizeof(err); 125 int sockoptret = getsockopt(fd,SOL_SOCKET,SO_ERROR,&err,&socklen); 126 if(sockoptret == -1) 127 { 128 return -1; 129 } 130 if(err == 0) 131 ret = 0; 132 else 133 { 134 errno = err; 135 ret = -1; 136 } 137 } 138 } 139 140 if(wait_seconds > 0) 141 { 142 deactivate_nonblock(fd); 143 } 144 return ret; 145 }
-
以上是关于Select模式和超时的主要内容,如果未能解决你的问题,请参考以下文章