在使用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/

最新文章

  1. 利用CSS背景颜色属性使父级div背景透明同时避免子级标签透明。
  2. 如何实现在PHP中调用JAVA
  3. HTML思维导图
  4. UIWindow 实现遮盖导航条的蒙版
  5. sql 查看 锁定的表 或者 未提交 的事务
  6. 论文阅读之 Inferring Analogous Attributes CVPR 2014
  7. Differences Between Xcode Project Templates for iOS Apps
  8. 重温《js权威指南》 第2-3章
  9. SQLServer处理亿万级别的数据的优化措施
  10. Android----二维码开发
  11. ETL构建数据仓库五步法
  12. Android学习----ADB
  13. datagrid指定行合并导出
  14. style-11bak
  15. Django unittest 单元测试
  16. python的对象 变量
  17. Oracle免安装绿色版-PLSQL连接报12154
  18. linux命令 xxd
  19. 微信小程序---获取上传图片大小
  20. 高可用Hadoop平台-集成Hive HAProxy

热门文章

  1. vue 重塑数组之 修改数组指定index的值
  2. calico在docker上的部署及验证
  3. Word2013 在一个页面双列显示
  4. SparseArray浅析
  5. TypeScript完全解读(26课时)_16.声明合并
  6. HDU1829【种类并查集】
  7. euler证明
  8. IT兄弟连 JavaWeb教程 EL表达式获取对象的属性以及数组的元素
  9. 企业级应用,如何实现服务化二(dubbo架构)
  10. go系列(3)- go框架beego以及redis的使用