用select实际非阻塞I/O
非阻塞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的更多相关文章
- 【Pyhton Network】使用poll()或select()实现非阻塞传输
通常情况下,socket上的I/O会阻塞.即除非操作结束,否则程序不会照常进行.而以下集中情况需要在非阻塞模式下进行:1. 网络接口在等待数据时是活动的,可以做出相应:2. 在不使用线程或进程的情况下 ...
- 非阻塞socket调用connect, epoll和select检查连接情况示例
转自http://www.cnblogs.com/yuxingfirst/archive/2013/03/08/2950281.html 我们知道,linux下socket编程有常见的几个系统调用: ...
- (转)非阻塞Connect对于select时应注意问题
对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后 ...
- 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...
- 转 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
此文章为转载,如有侵权,请联系本人.转载出处,http://blog.chinaunix.net/uid-28458801-id-4464639.html 同步(synchronous) IO和异步( ...
- TCP非阻塞accept和非阻塞connect
http://blog.chinaunix.net/uid-20751538-id-238260.html 非阻塞accept 当一个已完成的连接准备好被accept的时候,select会把监 ...
- Python 命令行非阻塞输入
很久很久以前,系windows平台下,用C语言写过一款贪食蛇游戏,cmd界面,用kbhit()函数实现非阻塞输入.系windows平台下用python依然可以调用msvcrt.khbit实现非阻塞监听 ...
- 面向连接的socket数据处理过程以及非阻塞connect问题
对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后 ...
- 同步IO,异步IO,阻塞IO,非阻塞IO
同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回.按照这个定义, 其实 ...
随机推荐
- BZOJ 1937 (luogu 4412) (KM+LCA)
题面 传送门 分析 根据贪心的思想我们得到几条性质: 1.生成树上的边权减小,非树边的边权增加 2.每条边最多被修改一次 设改变量的绝对值为d 对于一条非树边\(j:(u,v)\),树上u->v ...
- Java并发编程:进程的创建
Java并发编程:进程的创建 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...
- Codeforces Round #574 (Div. 2) A~E Solution
A. Drinks Choosing 有 $n$ 个人,每个人各有一种最喜欢的饮料,但是买饮料的时候只能同一种的两个两个买(两个一对) 学校只打算卖 $\left \lceil \frac{n}{2} ...
- 独立成分分析(Independent Component Analysis)
ICA是一种用于在统计数据中寻找隐藏的因素或者成分的方法.ICA是一种广泛用于盲缘分离的(BBS)方法,用于揭示随机变量或者信号中隐藏的信息.ICA被用于从混合信号中提取独立的信号信息.ICA在20世 ...
- react学习笔记_01-jsx
const element = <h1>Hello, world!</h1>; 首先我们看到声明了一个element元素,而他的内容并非字符串或者html. 它被称为 JSX, ...
- Ubuntu14.04(nginx+php+mysql+vsftp)配置安装流程
Ubuntu14.04(nginx+php+mysql+vsftp)配置安装流程 1.先切换到root用户 sudo su 2.更新软件源 apt update apt-get upgrade 3. ...
- 【Leetcode周赛】从contest-51开始。(一般是10个contest写一篇文章)
Contest 51 (2018年11月22日,周四早上)(题号681-684) 链接:https://leetcode.com/contest/leetcode-weekly-contest-51 ...
- JVM参数说明
转载于https://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html文章 JVM参数说明 -Xms:初始堆大小 默认值=物理内存的1 ...
- 前端移动开发--viewpoint
移动开发时,一般都会在头部加载这样一行meta标签 <meta name="viewport" content="width=device-width, initi ...
- session有效时间
request.getSession().setMaxInactiveInterval(-1);//session不失效 request.getSession().setMaxInactiveInte ...