我们为客户端的编写再做一些工作。

这次我们使用非阻塞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的实现的更多相关文章

  1. linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例

    除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnblogs.com/Anker/p/3265058.html 最简单的select示例: #incl ...

  2. linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例【转】

    转自:https://www.cnblogs.com/welhzh/p/4950341.html 除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnb ...

  3. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  4. Linux IO模式-阻塞io、非阻塞io、多路复用io

    一 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进程的阻塞 - 文件描述符 - 缓存 I/O 用户空间与内核空间 现在操作系统都是采用虚拟存储器,那么对3 ...

  5. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  6. Linux中同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  7. Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO

    背景 整理之前学习socket编程的时候复习到了多路复用,搜索了有关资料,了解到多路复用也有局限性,本着打破砂锅问到底的精神,最终找到了关于IO模型的知识点. 在<Unix网络编程>一书中 ...

  8. Linux IO 同步/异步 阻塞/非阻塞

    同步IO:导致请求进程阻塞,直到IO操作完成: 是内核通知我们何时进行启动IO操作,而实际的IO操作需要当前进程本身阻塞完成: 包括:阻塞式IO模型,非阻塞式IO模型,IO复用模型,信号驱动式IO模型 ...

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

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

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

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

随机推荐

  1. 汕头市队赛 SRM13 T2

    这道题很容易想到是二分 但是因为可能会爆LL 所以要加一波特判 #include<cstdio> #include<cstring> #include<algorithm ...

  2. hdu 6119 …&&百度之星 T6

    小小粉丝度度熊 Problem Description 度度熊喜欢着喵哈哈村的大明星——星星小姐. 为什么度度熊会喜欢星星小姐呢? 首先星星小姐笑起来非常动人,其次星星小姐唱歌也非常好听. 但这都不是 ...

  3. 百度之星初赛(A)——T2

    数据分割 小w来到百度之星的赛场上,准备开始实现一个程序自动分析系统. 这个程序接受一些形如x_i = x_jx​i​​=x​j​​ 或 x_i \neq x_jx​i​​≠x​j​​ 的相等/不等约 ...

  4. quartz 调度

    1.POI文件中导入包      <dependency> <groupId>org.quartz-scheduler</groupId> <artifact ...

  5. 重建二叉树_C++

    一.题目背景 给定一个二叉树的前序和中序遍历,求出它的后序遍历 二叉树的遍历可参考 http://blog.csdn.net/fansongy/article/details/6798278/ 二.算 ...

  6. 战斗机的祈雨仪式(NOIP模拟赛Round 7)

    [问题描述] 炎炎夏日,如果没有一场大雨怎么才能尽兴?秋之国的人民准备了一场祈雨仪式.战斗机由于拥有操纵雷电的能力,所以也加入了其中,为此,她进行了一番准备. 战斗机需要给自己的Spear of Lo ...

  7. 27.Remove Element---两指针

    题目链接:https://leetcode.com/problems/remove-element/description/ 题目大意:给出一个数组和一个值,从数组中删除与当前值相等的值,并将数组长度 ...

  8. JavaWeb响应下载(包含工具类)

    纸上得来终觉浅,绝知此事要躬行!今天博主分享是关于javaweb的响应(response)下载 以下是我的Demo: 页面我就粘主要部分的代码 <a href = "${pageCon ...

  9. Optional int parameter 'rows' is not present but cannot be translated into a null value due to being declared as a primitive type.

    我的spring mvc 代码: @Controller @RequestMapping("/product") public class Fancy { @RequestMapp ...

  10. (6)C#方法,作用域,方法重载

    1.方法 返回类型 方法名(参数列表) 例如:int a(int b,int c) { 方法体 return b+c; } 函数如果有返回类型则最后要用return一个和返回类型一样的数据. 2.无返 ...