在使用tcp的connect调用时,默认是使用阻塞方式,当服务器当前不可用时,connect会等待(内部在重试?)直到超时时间到达,而这个超时时间是系统内核规定的,不能使用setSocketOpt来设置。

在碰到服务器不可用,上层逻辑进行重试时,如果超时时间过长,会产生卡死的感觉,用户体验也不佳,所以需要控制connect的超时时间。

参考网络上的资料,这里使用select。实现方式是:将socket设置为非阻塞方式,使用select来轮询socket,在select里指定超时时间,根据socket来判断连接状态。最后恢复socket的阻塞方式。

代码如下(linux):

int connect_with_timeout(int socket, const struct sockaddr *address, socklen_t address_len, int time_out)
{
int flag, old_flag;
old_flag = flag = fcntl(socket, F_GETFL, );
flag |= O_NONBLOCK;
fcntl(socket, F_SETFL, flag); int ret = -;
ret = ::connect(socket, (struct sockaddr*)address, address_len);
if (ret != ) {
if (errno != EINPROGRESS) {
LOG("connect failed,err(%d)", errno);
} else {
struct timeval tm;
tm.tv_sec = time_out;
tm.tv_usec = ;
fd_set set,rset;
FD_ZERO(&set);
FD_ZERO(&rset);
FD_SET(socket, &set);
FD_SET(socket, &rset); int res;
res = ::select(socket+, &rset, &set, NULL, &tm);
if (res < ) {
LOG("select:network error in connect.errno:%d", errno);
} else if(res == ) {
LOG("select:connect timeout.errno:%d", errno);
} else if (res == ) {
if (FD_ISSET(socket, &set)) {
LOG("select success");
ret = ;
}
} else {
LOG("other error when select: %s", strerror(errno));
}
}
} fcntl(socket, F_SETFL, old_flag); return ret;
}

::connect在非阻塞模式下会立即返回,如果没有其他错误,返回值等于0。

当::connect不能立即建立连接时,会返回EINPROGRESS,表示正在连接的过程中,这时可以使用select去轮询套接口,而select超时时间由参数指定 。

select返回值小于0,表明connect出错;等于0,表明connect超时;等于1,并且套接口的状态是可写,则表明connect已经成功建立。

最后恢复socket的阻塞属性。

参考:

http://olive101.blog.163.com/blog/static/2051263201011221915696/

socket使用非阻塞connect的更多相关文章

  1. linux 客户端 Socket 非阻塞connect编程

    开发测试环境:虚拟机CentOS,windows网络调试助手        非阻塞模式有3种用途        1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...

  2. 面向连接的socket数据处理过程以及非阻塞connect问题

    对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后 ...

  3. UNIX网络编程-非阻塞connect和非阻塞accept

    1.非阻塞connect 在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长 ...

  4. TCP非阻塞accept和非阻塞connect

    http://blog.chinaunix.net/uid-20751538-id-238260.html 非阻塞accept     当一个已完成的连接准备好被accept的时候,select会把监 ...

  5. Socket,非阻塞,fcntl

    一.fcntl 用以下方法将socket设置成为非阻塞方式 int  flags = fcntl(socket,F_GETFL,0); fcntl(socket,F_SETFL,flags|O_NON ...

  6. [Python]再学 socket 之非阻塞 Server

    再学 socket 之非阻塞 Server 本文是基于 python2.7 实现,运行于 Mac 系统下 本篇文章是上一篇初探 socket 的续集, 上一篇文章介绍了:如何建立起一个基本的 sock ...

  7. UNIX网络编程——非阻塞connect: Web客户程序

    非阻塞的connect的实现例子出自Netscape的Web客户程序.客户先建立一个与某个Web服务器的HTTP连接,再获取一个主页.该主页往往含有多个对于其他网页的引用.客户可以使用非阻塞conne ...

  8. 网络编程之非阻塞connect编写

    一.connect非阻塞编写 TCP连接的建立涉及到一个三次握手的过程,且socket中connect函数需要一直等到客户接收到对于自己的SYN的ACK为止才返回, 这意味着每 个connect函数总 ...

  9. UE4 Socket多线程非阻塞通信

    转自:https://blog.csdn.net/lunweiwangxi3/article/details/50468593 ue4自带的Fsocket用起来依旧不是那么的顺手,感觉超出了我的理解范 ...

随机推荐

  1. kafka之六:为什么Kafka那么快

    转自:  http://mp.weixin.qq.com/s?__biz=MzIxMjAzMDA1MQ==&mid=2648945468&idx=1&sn=b622788361 ...

  2. ESXI中 Linux虚拟机不重启扩展磁盘

    1.首先对虚拟机进行编辑设置 硬盘大小进行修改到80G: 2.在Linux系统中查看磁盘大小 此时并没有什么变化: 3. 上面没有变化的原因,是因为需要重新扫描存储设备的scsi总线: 找到scsi磁 ...

  3. 09.客户端集成IdentityServer

    09.客户端集成IdentityServer 新建API的项目 dotnet new webapi --name ClientCredentialApi 在我们上一节课的代码IdentityServe ...

  4. Ubuntu18.04安装和配置Java JDK11并卸载自带OpenJDK

    卸载自带的OpenJDK方法: 在终端执行命令:sudo apt-get remove openjdk* Ubuntu18.04安装JDK11.0.2 前面步骤一样,可参考:https://www.c ...

  5. 移动端UI资源

    1.Flat UI Free http://designmodo.github.io/Flat-UI/ 2.POP 原型工具 http://mobilehub.io/products/pop 3.ei ...

  6. HDU2604【矩阵快速幂】

    思路: 把fm看成01,f-1,m-0: 不能存在101,111; dp[i]代表第i结尾的方案数: ①:结尾是0一定行:只要i-1序列里添个0就好了,dp[i]+=dp[i-1]: ②:结尾是1   ...

  7. bzoj5093:图的价值(第二类斯特林数+NTT)

    传送门 首先,题目所求为\[n\times 2^{C_{n-1}^2}\sum_{i=0}^{n-1}C_{n-1}^ii^k\] 即对于每个点\(i\),枚举它的度数,然后计算方案.因为有\(n\) ...

  8. [Xcode 实际操作]二、视图与手势-(1)UIView视图的基本使用

    目录:[Swift]Xcode实际操作 本文将演示在视图控制器的根视图里添加两个视图对象. import UIKit class ViewController: UIViewController { ...

  9. [Xcode 实际操作]八、网络与多线程-(14)使用网址会话对象URLSession将地理坐标转换为地名

    目录:[Swift]Xcode实际操作 本文将演示如果通过网址会话对象,将地理坐标转换为地名. 网址会话对象URLSession具有在后台上传和下载.暂停和恢复网络操作.丰富的代理模式等优点. 在项目 ...

  10. TTM-To the moon

    传送门 查询历史版本,回到历史版本,这个题目显然是用主席树,好像就没了! 但是这里的修改是区间修改,众所周知主席树的空间复杂度是\(nlog(n)\)的,区间修改会导致主席树的开点到达一个相当恐怖的数 ...