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);
View Code
  • 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 }
      View Code

       

以上是关于Select模式和超时的主要内容,如果未能解决你的问题,请参考以下文章

测试片段不执行定时器或示例超时

Go-并发模式2(Patterns)

channler多路选择和超时控制

select() 在长时间运行后立即超时 (C++)

如何在python的socket recv方法上设置超时?

nzSQLException 读取超时错误