connect 函数的调用涉及到TCP连接的三次握手过程,通常阻塞的connect 函数会等待三次握手成功或失败后返回,0成功,-1失败。如果对方未响应,要隔6s,重发尝试,可能要等待75s的尝试并最终返回超时,才得知连接失败。即使是一次尝试成功,也会等待几毫秒到几秒的时间,如果此期间有其他事务要处理,则会白白浪费时间,而用非阻塞的connect 则可以做到并行,提高效率。

而通常,非阻塞的connect 函数与 select 函数配合使用:在一个TCP套接口被设置为非阻塞之后调用connect,connect (函数本身返回-1)会立即返回EINPROGRESS或EWOULDBLOCK错误,表示连接操作正在进行中,但是仍未完成;同时TCP的三路握手操作继续进行;在这之后,我们可以调用select来检查这个链接是否建立成功。

若建立连接成功,select的结果中该描述符可写;若失败,则可写可读,此时可以使用getsockopt获取错误信息。

正常的三次握手时序

(以下内容转自http://blog.163.com/li_xiang1102/blog/static/60714076201110298170975/)

非阻塞connect有三种用途

  • 我们可以在三路握手的同时做一些其它的处理。connect 操作要花一个往返时间完成,而且可以是在任何地方,从几个毫秒的局域网到几百毫秒或几秒的广域网,在这段时间内我们可能有一些其他的处理想要执行;
  • 可以用这种技术同时建立多个连接.在Web浏览器中很普遍;
  • 由于我们使用select 来等待连接的完成,因此我们可以给select设置一个时间限制,从而缩短connect 的超时时间。在大多数实现中,connect 的超时时间在75秒到几分钟之间。有时候应用程序想要一个更短的超时时间,使用非阻塞connect 就是一种方法。

非阻塞connect 听起来虽然简单,但是仍然有一些细节问题要处理:

  • 即使套接口是非阻塞的。如果连接的服务器在同一台主机上,那么在调用connect 建立连接时,连接通常会立即建立成功,我们必须处理这种情况。
  • 源自Berkeley的实现(和Posix.1g)有两条与select 和非阻塞IO相关的规则:
    A. 当连接建立成功时,套接口描述符变成可写;
    B. 当连接出错时,套接口描述符变成既可读又可写。

    所以,套接字可读并不一定是连接以建立的标志。

处理非阻塞connect的步骤(重点):

  • 创建socket,返回套接口描述符;
  • 调用fcntl 把套接口描述符设置成非阻塞;
  • 调用connect 开始建立连接;
  • 判断连接是否成功建立。

判断连接是否成功建立:

  • 如果connect 返回0,表示连接成功(服务器和客户端在同一台机器上时就有可能发生这种情况);
  • 调用select 来等待连接建立成功完成;

如果select 返回0,则表示建立连接超时。我们返回超时错误给用户,同时关闭连接,以防止三路握手操作继续进行下去。如果select 返回大于0的值,则需要检查套接口描述符是否可写,如果套接口描述符可写,则我们可以通过调用getsockopt来得到套接口上待处理的错误(SO_ERROR)。如果连接建立成功,这个错误值将是0;如果建立连接时遇到错误,则这个值是连接错误所对应的errno值(比如:ECONNREFUSED,ETIMEDOUT等)。

代码示例

int conn_nonb(int sockfd, const struct sockaddr_in *saptr, socklen_t salen, int nsec)
{int flags, n, error, code;socklen_t len;fd_set wset;struct timeval tval;flags = fcntl(sockfd, F_GETFL, 0);fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);error = 0;if ((n == connect(sockfd, saptr, salen)) == 0) {goto done;} else if (n < 0 && errno != EINPROGRESS){return (-1);}/* Do whatever we want while the connect is taking place */FD_ZERO(&wset);FD_SET(sockfd, &wset);tval.tv_sec = nsec;tval.tv_usec = 0;if ((n = select(sockfd+1, NULL, &wset, NULL, nsec ? &tval : NULL)) == 0) {close(sockfd);  /* timeout */errno = ETIMEDOUT;return (-1);}if (FD_ISSET(sockfd, &wset)) {len = sizeof(error);code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);/* 如果发生错误,Solaris实现的getsockopt返回-1,* 把pending error设置给errno. Berkeley实现的* getsockopt返回0, pending error返回给error. * 我们需要处理这两种情况 */if (code < 0 || error) {close(sockfd);if (error) errno = error;return (-1);}} else {fprintf(stderr, "select error: sockfd not set");exit(0);}done:fcntl(sockfd, F_SETFL, flags);  /* restore file status flags */return (0);
}

非阻塞connect的作用及代码示例相关推荐

  1. linux下网络编程设置非阻塞,UNIX网络编程 非阻塞connect的实现

    一.<UNIX网络编程>-非阻塞connect 在一个TCP套接口被设置为非阻塞之后调用connect,connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未 ...

  2. 【网络编程】非阻塞connect详解

    一.为什么使用非阻塞connect TCP连接的建立涉及一个在三路握手过程,阻塞的connect一直等到客户收到自己的SYN的ACK才返回,这需要至少一个RTT时间,RTT时间波动很大从几毫秒到几秒. ...

  3. 非阻塞connect的实现

    步骤1: 设置非阻塞,启动连接 实现非阻塞 connect ,首先把 sockfd 设置成非阻塞的.这样调用 connect 可以立刻返回,根据返回值和 errno 处理三种情况: (1) 如果返回 ...

  4. 由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?

    一般情况下,我们像下面代码中所示的这样使用非阻塞connect: #include <stdio.h> #include <stdlib.h> #include <str ...

  5. 网络编程学习笔记(非阻塞connect)

    设置非阻塞,如果返回EINPROGRESS,表示正在建立连接,还没有完成 非阻塞的三个用途: 1.我们可以在三路握手的同时做其它的处理.connect要花一个往返时间完成,而且可以是在任何地主,从几个 ...

  6. linux fifo数据流,在linux / bash中使用非阻塞FIFO流式传输视频(示例代码)

    我正在努力实现以下目标: 将我的Raspberry Pi相机中的视频写入磁盘,不受任何流式干扰 通过网络流式传输相同的视频优化延迟 重要的是流不会干扰正在写入磁盘的视频,因为网络连接可能不稳定,例如W ...

  7. Linux高性能服务器I/0高级应用:非阻塞connect(15)

    前言 首linux系统下,connect函数是阻塞的,阻塞时间的长度与系统相关.而如果把套接字设置成非阻塞,调用connect函数时会报错Operation now in progress,且errn ...

  8. HDFS的API调用,创建Maven工程,创建一个非Maven工程,HDFS客户端操作数据代码示例,文件方式操作和流式操作

    1. HDFS的java操作 hdfs在生产应用中主要是客户端的开发,其核心步骤是从hdfs提供的api中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS上的文件 1.1 ...

  9. linux网络编程-----非阻塞connect

    libevent在内部由于使用io多路复用函数进行的事件监控,所以它所有的io读写操作都是非阻塞的,换句话说,libevent提供的接口函数evconnlistener_new_bind()和buff ...

  10. 非阻塞connect

    在 socket 是阻塞模式下 connect 函数会一直到有明确的结果才会返回(或连接成功或连接失败),如果服务器地址"较远",连接速度比较慢,connect 函数在连接过程中可 ...

最新文章

  1. oracle 开窗子句,分析函数和开窗函数
  2. java javaw区别
  3. win10重置此电脑_Windows 10更新导致“重置此电脑”失效 微软给出解决办法
  4. LeetCode-726. 原子的数量(python2)
  5. WebAPI(part12)--事件高级
  6. 数据结构与算法--二叉树第k个大的节点
  7. Istio 庖丁解牛六:多集群网格应用场景
  8. 【十四】无验证码登录配置:通过登录接口获取 token 配置全局变量
  9. hbase入门综合概要介绍
  10. mysql随机显示记录_mysql随机提取记录数的方法
  11. 调整数组顺序使奇数位于偶数前
  12. Java Web学习总结(6)Cookie/Session
  13. [Matlab科学计算] 绘制B样条基函数
  14. php工具箱升级MySQL
  15. idea activation code记录
  16. win10c盘清理(win10磁盘清理和磁盘整理)
  17. GA125整经机普罗菲斯触摸屏程序+西门子PLC S7-200程序
  18. 【AWS云从业者基础知识笔记】——模块1:AWS服务简介
  19. 有了它,药物研发将大大提速?
  20. Linux 文件rwx权限问题 chmod 777 XXX 任何人拥有最高权限

热门文章

  1. 还花几个小时整理线缆你就OUT了,VR自由漫步来了
  2. IDEA中如何配置Tomcat和项目?
  3. Widnows开启休眠
  4. Tomcat性能调优方案
  5. 4.性能之巅 洞悉系统、企业与云计算 --- 观测工具
  6. 7.SOA架构:服务和微服务分析及设计--- REST服务及微服务的服务API于契约设计
  7. 10.Shell 编程从入门到精通 --- 超级工具(shell,ssh,screen,vim)
  8. 5.HTTP 常见状态码
  9. 16. Zend_Controller
  10. 57. Attribute specified 属性