Linux非阻塞IO(四)非阻塞IO中connect的实现
我们为客户端的编写再做一些工作。
这次我们使用非阻塞IO实现connect函数。
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
非阻塞IO有以下用处:
1.将三次握手的处理过程生下来,处理其他事情。
2.使用这个同时建立多个连接。
3.实现超时connect功能,本节实现的connect就可以指定时间,超时后算作错误处理。
在阻塞IO中,调用connect后一般会阻塞,直到确定连接成功或者失败。
在Non-Blocking IO中,connect往往会立刻返回,此时connect就有两种结果。
一是连接成功
二是返回-1,errno置为EINPROGRESS,这种一般是因为网络延迟,所以连接不能马上建立,我们需要使用poll来监听sockfd。
所以接下来我们需要向poll注册sockfd的写事件。
《TCP/IP详解》第二卷指出以下的一些规则:
当连接建立时,sockfd可写。
当遇到错误时,sockfd既可读又可写。
我们设置一个超时时间,当poll返回时,如果sockfd可写,此时有两种情况:
一是连接确实建立成功
二是连接发生错误
我们需要某些手段辨别究竟是否发生了错误。
这里我们采用socket选项,检测的是SO_ERROR,代码如下:
int get_sockfd_error(int sockfd)
{
int err;
socklen_t socklen = sizeof(err);
if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &socklen) == -1)
ERR_EXIT("getsock_error error");
if (err == 0)
return 0; //无错误
else
return err;
}
如果sockfd无错误,则返回0,否则返回错误代码。
在非阻塞connect的实现中,我们通常需要先把fd设置为非阻塞,最后再重新设置为阻塞。这样做,是为了满足阻塞与非阻塞的需求。
因为在阻塞IO中,有时候也会使用非阻塞connect。
实现代码如下:
int nonblocking_connect(int sockfd, const char *des_host, uint16_t des_port, int timeout)
{
if(des_host == NULL)
{
fprintf(stderr, "des_host can not be NULL\n");
exit(EXIT_FAILURE);
} SAI servaddr;
memset(&servaddr, 0, sizeof servaddr);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(des_port);
if(inet_aton(des_host, &servaddr.sin_addr) == 0)
{
//DNS
//struct hostent *gethostbyname(const char *name);
struct hostent *hp = gethostbyname(des_host);
if(hp == NULL)
ERR_EXIT("gethostbyname");
servaddr.sin_addr = *(struct in_addr*)hp->h_addr;
} //设置为非阻塞
activate_nonblock(sockfd); //connect会立刻返回
int ret = connect(sockfd, (SA*)&servaddr, sizeof servaddr);
if(ret == -1)
{
if(errno != EINPROGRESS) //连接失败
ERR_EXIT("connect error");
struct pollfd pfd[1];
pfd[0].fd = sockfd;
pfd[0].events = POLLOUT; ret = poll(pfd, 1, timeout); if(ret == 0)
{
errno = ETIMEDOUT;
ret = -1; //连接超时,此时判定为失败
}
//sockfd可写,此时需要检查套接字选项,查看是否发生错误
else if(ret == 1 && pfd[0].revents & (POLLOUT | POLLWRBAND))
{
int err;
//检查sockfd错误
if((err = get_sockfd_error(sockfd)))
{
errno = err;
return -1;
}
}
} //重新设置为阻塞
deactivate_nonblock(sockfd);
return ret;
}
读者可以自行测试。
下节使用非阻塞connect实现客户端。
Linux非阻塞IO(四)非阻塞IO中connect的实现的更多相关文章
- linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例
除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnblogs.com/Anker/p/3265058.html 最简单的select示例: #incl ...
- linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例【转】
转自:https://www.cnblogs.com/welhzh/p/4950341.html 除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnb ...
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)
IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...
- Linux IO模式-阻塞io、非阻塞io、多路复用io
一 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进程的阻塞 - 文件描述符 - 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对3 ...
- 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- Linux中同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO
背景 整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点. 在<Unix网络编程>一书中 ...
- Linux IO 同步/异步 阻塞/非阻塞
同步IO:导致请求进程阻塞,直到IO操作完成: 是内核通知我们何时进行启动IO操作,而实际的IO操作需要当前进程本身阻塞完成: 包括:阻塞式IO模型,非阻塞式IO模型,IO复用模型,信号驱动式IO模型 ...
- 网络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和异步( ...
随机推荐
- Struts2的类型转换机制
Struts2的类型转换机制 在基于HITP 协胆的Web 应用中,客户端〈浏览器〉和服务器之间传输的都是字符串形式的数据,换句话说,服务器接收到的用户数据只能是字符串或字符数组, 但在服务器端的Ja ...
- mysql 连接失败问题汇集
FHost '192.168.5.128' is not allowed to connect to this MySQL serverConnection closed by foreign hos ...
- ssh xshell 连接在vim中无法用 ctrl+insert 复制黏贴
在用户目录编辑.vimrc文件不存在则创建,vi的三种模式:命令模式,插入模式,可视模式,鼠标可以启动于各种模式中,所以配置文件中的set mouse=a启动了所有模式,这样就屏蔽了鼠标右健功能,se ...
- Java错误随手记
一.Eclipse启动时提示: An internal error occurred during: "Initializing Java Tooling" 1.关闭Eclipse ...
- spring JPA写法一种
第一次用,搞了半天,终于知道了大概. 基于ORM的JPA还是蛮好用的, 这次是实现一个MANGODB的日志存储和检索. PRISM用的. repository的写法: package paic.sto ...
- 史上最全的web前端开发程序员学习清单!
今天为什么要给大家分享这篇文章呢,我发现最近来学前端的特别多,群里面整天都有人问:前端好找工作吗?前端要怎么学啊?前端工资怎么样?前端XX,前端XXX,虽然我回答过无数次这种问题了,但是问这个的还是有 ...
- 洛谷 U19159 采摘毒瘤
题目背景 Salamander见到路边有如此多的毒瘤,于是见猎心喜,从家里拿来了一个大袋子,准备将一些毒瘤带回家. 题目描述 路边共有nn 种不同的毒瘤,第i 种毒瘤有k_i 个,每个需要占据d_i ...
- POJ1655 Balancing Act(树的重心)
树的重心即树上某结点,删除该结点后形成的森林中包含结点最多的树的结点数最少. 一个DFS就OK了.. #include<cstdio> #include<cstring> #i ...
- python全栈开发- day14列表推导式、生成器表达式、模块基础
一.列表推导式 #1.示例 数据量小 egg_list=[] for i in range(10): egg_list.append('鸡蛋%s' %i) egg_list=['鸡蛋%s' %i fo ...
- yum安装openresty
在群里看到春哥发的,先记录下来.一切都以官网为准,以后安装部署生态会越来越完善的. OpenResty 官方现在开始维护自己的打包虚机集合了,新的 linux 包仓库正在陆续登陆 openresty. ...