前言

首linux系统下,connect函数是阻塞的,阻塞时间的长度与系统相关。而如果把套接字设置成非阻塞,调用connect函数时会报错Operation now in progress,且errno被设置为EINPROGRESS。下面将分析非阻塞时调用connect报错的原因

然后看看man手册

 EINPROGRESS
              The socket is nonblocking and the connection cannot be completed
              immediately.  It is possible to select(2) or poll(2) for comple‐
              tion by selecting the socket for writing.  After select(2) indi‐
              cates writability, use getsockopt(2) to read the SO_ERROR option
              at  level  SOL_SOCKET  to  determine whether connect() completed
              successfully (SO_ERROR is zero) or unsuccessfully  (SO_ERROR  is
              one  of the usual error codes listed here, explaining the reason
              for the failure).

简单来说就是

这段话描述了connect 出错时的一种errno值:EINPROGRESS。这种错误发生在对非阻
塞的socket调用connect,而连接又没有立即建立时
。根据man文档的解释,在这种情况下,我们可以调用select、poll等函数来监听这个连接失败的socket上的可写事件。当select、poll等函数返回后,再利用getsockopt来读取错误码并清除该socket上的错误。如果错误码是0,表示连接成功建立,否则连接失败。

代码示例

    #include<sys/socket.h>#include<sys/types.h>#include<netinet/in.h>#include<arpa/inet.h>#include<assert.h>#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<fcntl.h>#include<string.h>#include<errno.h>#include<sys/epoll.h>#include<pthread.h>#include<sys/ioctl.h>int setsocknoblock(int fd){int old_option=fcntl(fd,F_GETFL);int new_option=old_option|O_NONBLOCK;fcntl(fd,F_SETFL,new_option);return old_option;}/*parameter  meaningip         服务器端口信息port       端口号time       超时时间function preformancd:实现connect非阻塞*/int unblock_connect(const char* ip,int port,int time){int ret=0;struct sockaddr_in address;bzero(&address,sizeof(address));address.sin_family=AF_INET;address.sin_port=htons(port);inet_pton(AF_INET,ip,&address.sin_addr);int sockfd=(PF_INET,SOCK_STREAM,0);int fdopt=setsocknoblock(sockfd);ret=connect(sockfd,(struct sockaddr*)&address,sizeof(address));if(ret==0){printf("connect with server immediately\n");fcntl(sockfd,F_SETFD,fdopt);return sockfd;}else if(errno!=EINPROGRESS)//连接没有立即建立//errno 是EINPROGRESS时表示连接正在建立{printf("unblock connect not support\n");return -1;}fd_set readfds;fd_set writefds;struct timeval timeout;timeout.tv_sec=time;timeout.tv_usec=0;FD_ZERO(&readfds);FD_SET(sockfd,&writefds);ret=select(sockfd+1,NULL,&writefds,NULL,&timeout);if(ret<=0){//select 超时或者出错printf("connect time out\n");close(sockfd);return -1;}if(!FD_ISSET(sockfd,&writefds)){printf("no event no sockfd found");close(sockfd);return -1;}int error=0;socklen_t length=sizeof(error);if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&length)<0){printf("get socket option failed\n");close(sockfd);return -1;}if(error!=0){printf("connect failed after with the error %d\n",error);close(sockfd);return -1;}printf("connection ready after select with the socket :%d\n",sockfd);fcntl(sockfd,F_SETFD,fdopt);return sockfd;}int main(int argc,char* argv[]){if(argc<=2){printf("Usage %s ip_addresss port_number\n",basename(argv[0]));return 1;}const char* ip=argv[1];int port=atoi(argv[2]);int sockfd=unblock_connect(ip,port,10);assert(sockfd!=-1);close(sockfd);return -1;}

工作流程

注意:

但遗憾的是,这种方法存在几处移植性问题。首先,非阻塞的socket可能导致connect始终失败。其次,select对处于EINPROGRESS 状态下的socket可能不起作用。最后,对于出错的socket, getsockopt在有些系统(比如Linux)上返回-1(上面代码),而在有些系统(比如源自伯克利的UNIX)上则返回0。这些问题没有一个统一的解决方法,感兴趣的读者可自行参考相关文献。

Linux高性能服务器I/0高级应用:非阻塞connect(15)相关推荐

  1. Linux高性能服务器编程——书籍阅读笔记

    目录 前言 正文 第一章 1. 零拷贝函数 2. TCP/IP协议族 3. OSPF 4. ARP协议 5. RARP 6. ICMP协议 7. TCP协议 8. UDP协议 9. 封装 第四章 TC ...

  2. Linux 高性能服务器网络编程(一)

    Linux 高性能服务器网络编程 Linux网络编程基础API Socket 地址API 通用socket 地址 专用Sokect地址 IP地址转换函数 创建socket(socket) 命名(绑定) ...

  3. 《Linux高性能服务器编程》学习笔记

    <Linux高性能服务器编程>学习笔记 Linux高性能服务器编程 TCP/IP协议族 TCP/IP协议族体系结构以及主要协议 数据链路层 网络层 传输层 应用层 封装 分用 测试网络 A ...

  4. Linux 高性能服务器编程——多线程编程

    问题聚焦:     在简单地介绍线程的基本知识之后,主要讨论三个方面的内容:     1 创建线程和结束线程:     2 读取和设置线程属性:     3 线程同步方式:POSIX信号量,互斥锁和条 ...

  5. Linux 高性能服务器开发笔记:Reactor 模型定时器 | 网络编程定时器

    本文主要根据游双书本 Linux 高性能服务器开发 学习分析 linux 网络编程常用到的定时器模型,配备详细理解和分析,同时分析了 Linux 内核中定时器的低精度时间轮和高精度定时器实现思路还有 ...

  6. Linux高性能服务器开发——进程篇

    本文主要是学习Linux高性能服务器开发需要提前了解的知识,后续还会涉及到虚拟内存方面的内容,各位看官可以多了解了解,看到文章内有将的不清楚或者讲错的地方请各位一定留言,我看到后会第一时间验证并修正的 ...

  7. 《Linux高性能服务器编程》——导读

    前 言 为什么要写这本书 目前国内计算机书籍的一个明显弊病就是内容宽泛而空洞.很多书籍长篇大论,恨不得囊括所有最新的技术,但连一个最基本的技术细节也无法解释清楚.有些书籍给读者展现的是网络上随处可见的 ...

  8. 【Todo】【读书笔记】Linux高性能服务器编程

    在读 /Users/baidu/Documents/Data/Interview/服务器-检索端/<Linux高性能服务器编程.pdf> 其实之前读过,要面试了,需要温习. P260 So ...

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

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

最新文章

  1. oledb读不到dbf文件内容
  2. 成都铁路警方联合多部门开展反恐防暴演练
  3. 云原生思想 — 云原生应用
  4. ibatis学习笔记(三)java实体跟表映射.xml文件详解
  5. 用U盘作为启动盘,安装Yosemite
  6. 随想录(做自己代码的测试工程师)
  7. 第3章 flappy bird作业、SVN、GIT、码云
  8. Python SQLite教程
  9. 编程之美2.2 不要被阶乘吓到
  10. 使用zlog实现日志记录
  11. 每个国家对应的语言Locale和国家代码对照表
  12. depends工具查看exe和dll依赖关系
  13. 利用EXCEL将中文汉字转为拼音
  14. 虾皮马来西亚站如何选品?附快速出单秘诀
  15. 通过SQL语句数据库简繁体转换
  16. 用MATLAB对语音进行基频搬移,语音信号变声处理系.doc
  17. 携程Java后台开发面经
  18. php获取index.php,index.php · 阿彪/PHP去抖音水印解析-非接口(获取抖音无水印URL地址) - Gitee.com...
  19. lammps教程:平均值输出fix ave/time命令详解
  20. 错题本——数据结构(线性表)

热门文章

  1. 手机app开发可选技术——webview
  2. 微软Surface低端版本将问世
  3. JavaWeb项目:新闻发布系统01(登录新闻增加)
  4. JS实现眼睛跟随鼠标特效
  5. Flexbox设计H5应用网页布局
  6. RHCE(chrony服务器)
  7. RAD Studio 10.4.1新的基于Chromium的Microsoft Edge浏览器的TEdgeBrowser控件用法
  8. 订单号的生成规则和不同生成策略-总结
  9. 生产者消费者模式(1)
  10. (二)Spring Security自定义登录成功或失败处理器