一、概述

linux系统下,connect函数是阻塞的,阻塞时间的长度与系统相关。而如果把套接字设置成非阻塞,调用connect函数时会报错Operation now in progress,且errno被设置为EINPROGRESS。下面将分析非阻塞时调用connect报错的原因,以及提供两个方法解决connet函数阻塞太久的问题。

二、connect函数报Operation now in progress的原因

connect函数报错Operation now in progress,且errno被设置为EINPROGRESS的原因是套接字被设置为非阻塞了。建立TCP连接会涉及到三次握手的过程,connect函数会一直等到收到自己的SYN的ACK为止,所以会阻塞一段时间;如果套接字设置成非阻塞,connect函数会立即返回,但此时已经发起的TCP三次握手仍在进行,所以connect会返回一个EINPROGRESS错误,表示操作正在进行中(Operation now in progress)。

三、解决connet函数阻塞太久的问题

三次握手的过程就决定了connect函数是需要阻塞一段时间的,而我们是向避免它阻塞太久了,影响程序执行。下面提供2个可行的方法,仅供参考。

3.1 设置成非阻塞,且使用select等到连接的建立

// 接服务器并返回套接字,timeoutMs 毫秒
int tcpClientConnect(unsigned int u32SerIp, unsigned short port, int timeoutMs)
{// 1、创建tcp套接字int sockFd = -1;if ((sockFd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { printf("[%s %d] socket failed\n",__FILE__,__LINE__); return -1;} // 2、socket 设置非阻塞int flags = fcntl(sockFd,F_GETFL,0);if(-1 == fcntl(sockFd,F_SETFL,flags|O_NONBLOCK)){printf("Set socket unblock failed!");}// 3、准备服务器地址信息、连接struct sockaddr_in server_addr;; server_addr.sin_family=PF_INET; server_addr.sin_port=htons(port); server_addr.sin_addr.s_addr = u32SerIp; bzero(&(server_addr.sin_zero), 0); if (connect(sockFd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0){if(errno != EINPROGRESS){printf("[%s %d] Connect fail!\n",__FILE__,__LINE__);close(sockFd);return -1;}}// 4、select等待fd_set rset,wset;FD_ZERO(&rset);FD_SET(sockFd,&rset);wset = rset;struct timeval tv;tv.tv_sec = timeoutMs/1000;tv.tv_usec = (timeoutMs%1000)*1000;if(select(sockFd+1, &rset, &wset, NULL, &tv)==0){printf("[%s %d] select fail!\n",__FILE__,__LINE__);close(sockFd);return -1;      }if(FD_ISSET(sockFd,&rset) || FD_ISSET(sockFd,&wset)){int error;socklen_t len = sizeof(error);if(getsockopt(sockFd, SOL_SOCKET, SO_ERROR, &error, &len)<0)return -1;    }printf("[%s %d] Connect pass! %d\n",__FILE__,__LINE__,sockFd);return sockFd;
}

3.2 使用套接字选项设置发送超时

// timeoutMs 毫秒
int tcpClientConnect(uint32_t u32SerIp, uint16_t port, int timeoutMs)//连接服务器并放回套接字 2022-06-23 20:02:34
{// 1、创建tcp套接字int sockFd = -1;if ((sockFd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { printf("[%s %d] socket failed\n",__FILE__,__LINE__); return -2;} // 2、设置 sockFd 超时时间*/if(timeoutMs > 0){struct timeval tv;tv.tv_sec = timeoutMs/1000;tv.tv_usec = (timeoutMs%1000)*1000;setsockopt(sockFd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));}// 3、准备服务器地址信息、连接struct sockaddr_in server_addr;; server_addr.sin_family=PF_INET; server_addr.sin_port=htons(port); server_addr.sin_addr.s_addr = u32SerIp; bzero(&(server_addr.sin_zero), 0); if (connect(sockFd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0){printf("[%s %d] Connect fail!\n",__FILE__,__LINE__);close(sockFd);return -1;}printf("[%s %d] Connect pass! %d\n",__FILE__,__LINE__,sockFd);return sockFd;
}

(650条消息) Linux下connect函数 阻塞 与 非阻塞 问题_wkd_007的博客-CSDN博客_connect linux

Linux下connect函数 阻塞 与 非阻塞 问题相关推荐

  1. linux函数阻塞,Linux下connect()函数阻塞与非阻塞

    各位好,今天遇到一个奇怪的问题.在写socket客户端的程序时,发现connect()函数有时阻塞,有时非阻塞.且大部分时间是非阻塞的.下面是代码: socket_list[i].socket = s ...

  2. linux非阻塞输入函数,Linux fcntl函数设置阻塞与非阻塞

    转自http://www.cnblogs.com/xuyh/p/3273082.html 用命令F_GETFL和F_SETFL设置文件标志,比如阻塞与非阻塞 F_SETFL     设置给arg描述符 ...

  3. connect函数在阻塞和非阻塞模式下的行为

    connect函数在阻塞和非阻塞模式下的行为 当socket使用阻塞模式时,connect函数会阻塞到有明确结果才会返回,如果网络环境较差,可能要等一会,影响体验, 为了解决这个问题,我们使用异步co ...

  4. socket的阻塞模式和非阻塞模式(send和recv函数在阻塞和非阻塞模式下的表现)

    socket的阻塞模式和非阻塞模式 无论是Windows还是Linux,默认创建socket都是阻塞模式的 在Linux中,可以再创建socket是直接将它设置为非阻塞模式 int socket (i ...

  5. linux函数的阻塞与非阻塞IO及错误处理

    linux函数的阻塞与非阻塞IO及错误处理 1.阻塞是指进程等待某一个事件的发生而处于等待状态不往下执行,如果等待的事件发生了则会继续执行该进程.调用系统阻塞函数可能会导致进程阻塞进入睡眠状态. 2. ...

  6. linux下recv 、send阻塞、非阻塞区别和用法

    非阻塞IO 和阻塞IO: 在网络编程中对于一个网络句柄会遇到阻塞IO 和非阻塞IO 的概念, 这里对于这两种socket 先做一下说明:        基本概念: 阻塞IO:: socket 的阻塞模 ...

  7. linux下的阻塞和非阻塞

            读常规文件是不会阻塞的,不管读多少字节,read 一定会在有限的时间内返回.从终 端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用 read 读终端设备就会 阻塞,如果网络 ...

  8. linux下阻塞的系统调用,Linux下文件的阻塞与非阻塞对部分系统调用的影响

    1.基本概念 所谓的阻塞,即内核在对文件操作I/O系统调用时,如果条件不满足(可能需要产生I/O),则内核会将该进程挂起.非阻塞则是发现条件不满足就会立即返回.此外需要注意的是非阻塞并不是轮询,不然就 ...

  9. linux fcntl 设置阻塞,Linux fcntl函数设置阻塞与非阻塞

    转自http://www.cnblogs.com/xuyh/p/3273082.html 用命令F_GETFL和F_SETFL设置文件标志,比如阻塞与非阻塞 F_SETFL     设置给arg描述符 ...

最新文章

  1. 数据库相关(JDBC,存储过程,以及大文本数据处理,mvc设计模式)
  2. Jenkins Pipeline高级用法-ShareLibrary
  3. ORACLE一致读与ORA-01555
  4. 2014 ACM/ICPC Asia Regional Xi'an Online
  5. Oracle NID工具修改数据库DBID和数据库名称
  6. error C2265: 'Unknown' : reference to a zero-sized array is illegal
  7. Diameter协议学习笔记一(协议介绍)
  8. 新中大财务软件V5.08安装
  9. 苹果手机怎样软件签名?
  10. 【机器学习】如何使用随机网格搜索,以缩短网格搜索速度?
  11. [RE]如何调整堆栈平衡
  12. 结构体定义 typedef struct LNode 用法说明
  13. CausalImpact
  14. android自定义系统屏保Dream
  15. unity中计算三角形的外接圆
  16. 获奖团队访谈录|“AI+无线通信赛道”二等奖团队
  17. 小米布局金融5年:新网银行遭银保监通报侵权,小米数科被列入经营异常
  18. 为什么理想电流源的等效内阻是无限大
  19. SLife 共享生活:去中心化的线下商业交易系统
  20. 毕业一年,程序猿工作一年总结,有收获,有失去,有遗憾,但仍一往无前

热门文章

  1. Linux--历史、安装
  2. pycharm运行小游戏
  3. SFM之通过exif获取初始焦距
  4. 恶搞,自动打开特定网站
  5. UI设计中的交互设计原则有哪些?
  6. 教你如何通过ssh控制远程主机,远程执行命令
  7. 阿里巴巴马云关于创新
  8. ssh远程执行命令的方法
  9. 大厂面经:四轮字节面试究竟问了些什么?
  10. [9i] 2019新年临近,常用的关于新年方面的单词和祝福语