非阻塞read/write

函数返回0表示可读或可写, -1表示select失败或超时

select返回0表示超时,-1表示读取失败,1表示可读或可写

int read_timeout(int fd,unsigned int wait_seconds){
int ret=0;
if(wait_seconds > 0){
fd_set read_fdset;
struct timeval timeout; FD_ZERO(&read_fdset);
FD_SET(fd,&read_fdset); timeout.tv_sec=wait_seconds;
timeout.tv_usec=0;
do{
ret=select(fd+1,&read_fdset,NULL,NULL,&timeout);
}while(ret < 0 && errno == EINTR); if(ret == 0){
ret = -1;
errno=ETIMEDOUT;
}else if(ret == 1)
ret = 0;
} return ret;
} int write_timeout(int fd,unsigned int wait_seconds){
int ret=0;
if(wait_seconds > 0){
fd_set write_fdset;
struct timeval timeout; FD_ZERO(&write_fdset);
FD_SET(fd,&write_fdset); timeout.tv_sec=wait_seconds;
timeout.tv_usec=0;
do{
ret=select(fd+1,NULL,&write_fdset,NULL,&timeout);
}while(ret < 0 && errno == EINTR); if(ret == 0){
ret = -1;
errno = ETIMEDOUT;
}else if(ret == 1)
ret = 0;
}
return ret;
}

非阻塞connect

非阻塞connect需要辅助函数fcntl

select返回值分析同read/write, 当connect连接成功或失败,返回的fd都处于可写状态

所以当select返回1时,需要再次判断connect是否连接成功

判断方法:

1.通过getsockopt获取soketfd是否存在错误

2.通过getpeername判断对方地址是否存在

3.再次调用connect,判断是否返回错误码EISCONN(连接已建立)

void activate_nonblock(int fd){
int ret;
int flags=fcntl(fd,F_GETFL);
if(flags == -1)
err_quit("fcntl"); flags |= O_NONBLOCK;
ret=fcntl(fd,F_SETFL,flags);
if(ret == -1)
err_quit("fcntl");
} void deactivate_nonblock(int fd){
int ret;
int flags=fcntl(fd,F_GETFL);
if(flags == -1)
err_quit("fcntl"); flags &= ~O_NONBLOCK;
ret=fcntl(fd,F_SETFL,flags);
if(ret == -1)
err_quit("fcntl");
} int connect_timeout(int fd,struct sockaddr_in *addr,unsigned int wait_seconds){
int ret;
socklen_t addrlen=sizeof(struct sockaddr_in); if(wait_seconds > 0)
activate_nonblock(fd); ret=connect(fd,(struct sockaddr *)addr,addrlen);
if(ret < 0 && errno == EINPROGRESS){
fd_set connect_fdset;
struct timeval timeout; FD_ZERO(&connect_fdset);
FD_SET(fd,&connect_fdset); timeout.tv_usec=0;
timeout.tv_sec=wait_seconds;
do{
ret=select(fd+1,NULL,&connect_fdset,NULL,&timeout);
}while(ret < 0 && errno == EINTR); if(ret == 0){
ret = -1;
errno = ETIMEDOUT;
}else if(ret < 0)
return -1;
else if(ret == 1){
int err;
socklen_t socklen=sizeof(err);
int sockoptret=getsockopt(fd,SOL_SOCKET,SO_ERROR,&err,&socklen);
if(sockoptret == -1){
return -1;
}else if(err == 0){
return 0;
}else{
errno = err;
ret = -1;
}
}
} if(wait_seconds > 0)
deactivate_nonblock(fd); return ret;
}

非阻塞accecpt

int accept_timeout(int fd,struct sockaddr_in *addr,unsigned int wait_seconds){
int ret;
socklen_t addrlen=sizeof(struct sockaddr_in); if(wait_seconds > 0){
fd_set accept_fdset;
struct timeval timeout; FD_ZERO(&accept_fdset);
FD_SET(fd,&accept_fdset); timeout.tv_usec=0;
timeout.tv_sec=wait_seconds;
do{
ret=select(fd+1,&accept_fdset,NULL,NULL,&timeout);
}while(ret < 0 && errno == EINTR); if(ret == 0){
errno = ETIMEDOUT;
return -1;
}else if(ret == -1)
return -1;
} if(addr != NULL)
ret=accept(fd,(struct sockaddr *)addr,&addrlen);
else
ret=accept(fd,NULL,NULL);
if(ret == -1)
err_quit("accept"); return ret;
}

用select实际非阻塞I/O的更多相关文章

  1. 【Pyhton Network】使用poll()或select()实现非阻塞传输

    通常情况下,socket上的I/O会阻塞.即除非操作结束,否则程序不会照常进行.而以下集中情况需要在非阻塞模式下进行:1. 网络接口在等待数据时是活动的,可以做出相应:2. 在不使用线程或进程的情况下 ...

  2. 非阻塞socket调用connect, epoll和select检查连接情况示例

    转自http://www.cnblogs.com/yuxingfirst/archive/2013/03/08/2950281.html 我们知道,linux下socket编程有常见的几个系统调用: ...

  3. (转)非阻塞Connect对于select时应注意问题

    对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后 ...

  4. 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...

  5. 转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO

    此文章为转载,如有侵权,请联系本人.转载出处,http://blog.chinaunix.net/uid-28458801-id-4464639.html 同步(synchronous) IO和异步( ...

  6. TCP非阻塞accept和非阻塞connect

    http://blog.chinaunix.net/uid-20751538-id-238260.html 非阻塞accept     当一个已完成的连接准备好被accept的时候,select会把监 ...

  7. Python 命令行非阻塞输入

    很久很久以前,系windows平台下,用C语言写过一款贪食蛇游戏,cmd界面,用kbhit()函数实现非阻塞输入.系windows平台下用python依然可以调用msvcrt.khbit实现非阻塞监听 ...

  8. 面向连接的socket数据处理过程以及非阻塞connect问题

    对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后 ...

  9. 同步IO,异步IO,阻塞IO,非阻塞IO

    同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回.按照这个定义, 其实 ...

随机推荐

  1. 点分治题单(来自XZY)

    点分治题单(来自XZY) 静态点分治 [x] 洛谷 P3806 [模板]点分治1 [x] 洛谷 P4178 Tree [x] 洛谷 P2634 [国家集训队]聪聪可可 [x] 洛谷 P4149 [IO ...

  2. P3806 【模板】点分治1(题解)(点分治)

    P3806 [模板]点分治1(题解)(点分治) 洛谷题目传送门 #include<iostream> #include<cstdlib> #include<cstdio& ...

  3. Linux服务器安全配置小结(转)

    众所周知,网络安全是一个非常重要的课题,而服务器是网络安全中最关键的环节.Linux被认为是一个比较安全的Internet服务器,作为一种开放源代码操作系统,一旦Linux系统中发现有安全漏洞,Int ...

  4. java、javaw和javaws的区别

    java.javaw和javaws的区别: 首先,所有的这些都是java的启动装置,java.exe经常使用,当使用命令行输出到window的时候,会有java.exe进程,通过任务管理器可以看到.通 ...

  5. mpvue 微信小程序半屏弹框(half-screen-dialog)

    <template> <div> <a @click="isShow">half-screen-dialog</a> <!-- ...

  6. android&iOS设计分辨率

    --- iPhone --- iPhone SE 1136 * 640 2.0875 iPhone 6 1334 * 750 1.778666666666667 iPhone X 2436 * 112 ...

  7. Linux Shell 脚本学习第一天: 使用grep 命令,lsusb, ps -ef, 实现树莓派(Debian OS)时检测到依赖的USB设备启动后,启动终端自动执行shell脚本

    1.应用背景: 无人监测的设备,常需要设置应用程序开机启动,程序启动前需要保证调用的设备先启动,运行环境先启动. 2.test.sh部分源码 #!/bin/sh #查看桌面是否启动 while tru ...

  8. BJSV-P-004无缝大屏显示

    无缝大屏显示 北京太速科技有限公司在线客服:QQ:448468544 淘宝网站:orihard.taobao.com/?联系电话:15084122580 欢迎关注微信公众号 啊智能时代

  9. Deepin学习笔记

    更改更新源 1)sudo vim /etc/apt/sources.list 2)sudo apt-get update 3)  镜像源 http://mirrors.aliyun.com/deepi ...

  10. HDU-5378 概率DP

    题意:给定一棵有n个节点的树,现在要给节点附1~n的权值(各节点权值不能相同),一棵子树的领袖就是子树中权值最大的节点,问有多少种分配方案使得最后有恰好K个领袖. 解法:这道题一看以为是树上的计数问题 ...