非阻塞的connect函数和select函数

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

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

 

处理非阻塞connect的步骤(重点):
1. 创建socket,返回套接口描述符;
2. 调用fcntl 把套接口描述符设置成非阻塞;
3. 调用connect 开始建立连接;
4. 判断连接是否成功建立。

判断连接是否成功建立:
A. 如果connect 返回0,表示连接成功(服务器和客户端在同一台机器上时就有可能发生这种情况);
B. 调用select 来等待连接建立成功完成;
     如果select 返回0,则表示建立连接超时。我们返回超时错误给用户,同时关闭连接,以防止三路握手操作继续进行下去。
     如果select 返回大于0的值,则需要检查套接口描述符是否可写,如果套接口描述符可写,则我们可以通过调用getsockopt来得到套接口上待处理的错误(SO_ERROR)。如果连接建立成功,这个错误值将是0;如果建立连接时遇到错误,则这个值是连接错误所对应的errno值(比如:ECONNREFUSED,ETIMEDOUT等)。


 

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值