• read,write,accept,connect 超时封装


    //read操作加上超时时间。
    1
    int read_timeout(int fd, void *buf, uint32_t count, int time) 2 { 3 if(time > 0) { 4 fd_set rSet; 5 FD_ZERO(&rSet); 6 FD_SET(fd, &rSet); 7 8 struct timeval timeout; 9 memset(&timeout, 0, sizeof(timeout)); 10 timeout.tv_sec = time; 11 timeout.tv_usec = 0; 12 13 int ret; 14 while(1) { 15 ret = select(fd+1, &rSet, NULL, NULL, &timeout); 16 if(ret < 0) { 17 if(errno == EINTR) continue; 18 ERR_EXIT("select"); 19 } else if(ret == 0) { 20 errno = ETIMEDOUT; 21 return -1; 22 } else { 23 break; 24 } 25 } 26 } 27 int readNum; 28 readNum = read(fd, buf, count); 29 return readNum; 30 }

    写超时

     1 int write_timeout(int fd, void *buf, uint32_t count, int time)
     2 {
     3     if(time > 0) {
     4         fd_set wSet;
     5         FD_ZERO(&wSet);
     6         FD_SET(fd, &wSet);
     7 
     8         struct timeval timeout;
     9         memset(&timeout, 0, sizeof(timeout));
    10         timeout.tv_sec = time;
    11         timeout.tv_usec = 0;
    12         
    13         int ret;
    14         while(1) {
    15             ret = select(fd+1, NULL, &wSet, NULL, &timeout);
    16             if(ret < 0) {
    17                 if(errno == EINTR) continue;
    18                 ERR_EXIT("select");
    19             } else if(ret == 0) {
    20                 errno = ETIMEDOUT;
    21                 return -1;
    22             } else {
    23                 break;
    24             }
    25         }
    26     }
    27     int writeNum;
    28     writeNum = write(fd, buf, count);
    29     return writeNum;
    30 }

    accept超时操作

    int accept_timeout(int fd, struct sockaddrin *addr, socklen_t *addrlen, int time)
    {
        int ret;
        if(time > 0) {
            fd_set rSet;
            FD_ZERO(&rSet);
            FD_SET(fd, &rSet);
    
            struct timeval timeout;
            timeout.tv_sec = time;
            timeout.tv_usec = 0;
    
            int selectRet;
            do {
                selectRet = select(fd + 1, &rSet, NULL, NULL, &timeout);
            }while(selectRet < 0 && selectRet == EINTR);
            if(selectRet < 0 ) {
                return -1;
            } else if(selectRet == 0) {
                errno = ETIMEDOUT;
                return -1;
            }    
        }
        if(addr) {
            ret = accept(fd, (struct sockaddr *)addr, addrlen);
        } else {
            ret = accept(fd, NULL, NULL);
        }
        return ret;
    }

    检测监听套接字是否可读,当监听套接字可读的时候,就认为连接队列发生了连接。

    connect

     1 void setNonBlockMode(int fd)
     2 {
     3     int flags = fcntl(fd, F_GETFL);
     4     if(flags < 0) {
     5         ERR_EXIT("fcntl");
     6     }
     7     flags |= O_NONBLOCK;
     8     if(fcntl(fd, F_SETFL, flags) < 0) {
     9         ERR_EXIT("fcntl");
    10     }
    11 }
    12 
    13 void setBlockMode(int fd)
    14 {
    15     int flags = fcntl(fd, F_GETFL);
    16     if(flags < 0) {
    17         ERR_EXIT("fcntl");
    18     }
    19     flags &= ~O_NONBLOCK;
    20     if(fcntl(fd, F_SETFL, flags) < 0) {
    21         ERR_EXIT("fcntl");
    22     }
    23 
    24 }
    25 
    26 int connect_timeout(int sockfd, struct sockaddrin *addr, socklen_t addrlen, int time)
    27 {
    28     int ret = -1;
    29 
    30     if(time > 0) {
    31         setNonBlockMode(sockfd);
    32     }    
    33     ret = connect(sockfd, (struct sockaddr*)addr, addrlen);
    34     if(ret < 0 && errno == EINPROGRESS) {
    35         fd_set wSet;
    36         FD_ZERO(&wSet);
    37         FD_SET(sockfd, &wSet);
    38         
    39         struct timeval timeout;
    40         timeout.tv_sec = time;
    41         timeout.tv_usec = 0;
    42         
    43         int selcetRet;
    44         do{
    45             selcetRet = select(sockfd + 1, NULL, &wSet, NULL, &timeout);
    46         }while(selcetRet < 0 && errno == EINTR);
    47         if(selcetRet < 0) {
    48             ret = -1;
    49         } else if(selcetRet == 0) {
    50             ret = -1;
    51             errno = ETIMEDOUT;
    52         } else if(selcetRet > 0) {
    53             int err;
    54             socklen_t socklen = sizeof(err);
    55             int sockoptRet = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &socklen);
    56             if(sockoptRet == -1) {
    57                 ret = -1;
    58             } 
    59             if(err == 0) {
    60                 ret = 0;
    61             } else {
    62                 errno = err;
    63                 ret = -1;
    64             }
    65         }
    66     }
    67     if(time > 0) {
    68         setBlockMode(sockfd);
    69     }
    70     return ret;
    71 }

    1.设置fd为非阻塞模式。

    2.调用connect操作,如果网络条件很好,比如本机两个socket发生连接,会发生成功返回。

    3.正常情况下,connect立即返回-1并设置errno为EINPROGRESS 表示正在连接过程中。

    4.使用select检测fd是否可写。 如果检测到可写也有如下两种情况:

      1. connect连接成功。

      2. 产生了错误,我们就需要用getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &socklen); 来判断是否发生了错误。

  • 相关阅读:
    安装oracle11g服务端
    安装oracle11g客户端
    Python生成requirements.txt方法
    oracle创建新用户并授予权限
    正向代理与反向代理【总结】
    使用Eclipse调试Java程序的10个技巧
    如果长颈鹿哭了,它会不会要哽咽好久
    你应该知道的10种软件工具
    我希望在20岁时就知道的26条时间管理技巧
    Vue使用NProgress (NProgress是页面跳转是出现在浏览器顶部的进度条)
  • 原文地址:https://www.cnblogs.com/superPerfect/p/3603427.html
Copyright © 2020-2023  润新知