博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
read,write,accept,connect 超时封装
阅读量:6147 次
发布时间:2019-06-21

本文共 4574 字,大约阅读时间需要 15 分钟。

//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); 来判断是否发生了错误。

 

 

 

转载于:https://www.cnblogs.com/superPerfect/p/3603427.html

你可能感兴趣的文章
JavaScript面向对象编程深入分析(2)
查看>>
linux 编码转换
查看>>
POJ-2287 Tian Ji -- The Horse Racing 贪心规则在动态规划中的应用 Or 纯贪心
查看>>
Windows8/Silverlight/WPF/WP7/HTML5周学习导读(1月7日-1月14日)
查看>>
关于C#导出 文本文件
查看>>
使用native 查询时,对特殊字符的处理。
查看>>
maclean liu的oracle学习经历--长篇连载
查看>>
ECSHOP调用指定分类的文章列表
查看>>
分享:动态库的链接和链接选项-L,-rpath-link,-rpath
查看>>
Javascript一些小细节
查看>>
禁用ViewState
查看>>
Android图片压缩(质量压缩和尺寸压缩)
查看>>
nilfs (a continuent snapshot file system) used with PostgreSQL
查看>>
【SICP练习】150 练习4.6
查看>>
HTTP缓存应用
查看>>
KubeEdge向左,K3S向右
查看>>
DTCC2013:基于网络监听数据库安全审计
查看>>
CCNA考试要点大搜集(二)
查看>>
ajax查询数据库时数据无法更新的问题
查看>>
Kickstart 无人职守安装,终于搞定了。
查看>>