• 非阻塞connect详情介绍可以参见文章:https://blog.csdn.net/qq_41453285/article/details/89890429

一、非阻塞connect概述

man手册

  • connect的man手册有如下一段内容:

EINPROGRESSThe socket is nonblocking and the connection cannot be completed immediately.  It is possible to select(2) or poll(2)  for  com‐pletion  by  selecting  the  socket  for writing.  After select(2) indicates 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 ofthe usual error codes listed here, explaining the reason for the failure).

  • 解析文档,非阻塞connect如何使用:

    • ①当我们将sock设置为非阻塞之后,使用connect去连接服务端,即使服务端开启了,connect系统调用也不会连接成功,connect而是以失败告终,并返回错误
    • ②但是非阻塞connect返回的错误是有讲究的:
      • 如果非阻塞connect返回的错误是EINPROGRESS,代表不是connect系统调用出错了,而是connect可能会在后面才会建立完整地连接(只是当前连接还没有建立完整),所以我们可以在通过给select、pol或epoll设置等待时间,来等待这个connect的连接成功,从而进一步处理
      • 如果非阻塞connect返回的错误不是EINPROGRESS,代表就是connect系统调用本身出错了,那么就可以做一些相应的错误处理了
    • ③当非阻塞connect以EINPROGRESS错误返回之后,我们可以给select、pol或epoll设置等待时间,并将客户端封装在等待可写的结构中,进一步来等待非阻塞connect客户端与服务端建立完整地连接,在等待的过程中,如果非阻塞connect建立成功了,客户端的sock_fd就会变成可写的(这个在本人的IO复用文章中介绍过,见下图)
    • ④当非阻塞connect建立成功之后还可以利用getsockopt来读取错误码并清除该socket上的错误:
      • 如果错误码为0,表示连接成功建立
      • 否则连接失败

二、非阻塞connect的移植性问题

  • 移植性问题如下:

    • 1.首先,非阻塞的socket可能导致connect始终失败
    • 2.其次,select对处于EINPROGRESS状态下的socket可能不起作用
    • 3.最后,对于出错的socket,getsockopt在有些系统(比如Linux)上返回-1,而在有些系统上(比如源自伯克利的UNIX)返回0
  • 这些问题没有一个统一的解决办法

三、编码演示案例

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <strings.h>
#include <libgen.h> //for basename
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <sys/select.h>
#include <arpa/inet.h>int setnonblocking(int fd);int set_nonblocking_connect(const char* ip,const char* port,int time);int main(int argc,char *argv[])
{//must write ip and portif(argc<3){printf("usage:./%s [ip] [port]\n",basename(argv[0]));exit(EXIT_FAILURE);}int cli_fd;if((cli_fd=set_nonblocking_connect(argv[1],argv[2],10))==-1) exit(EXIT_FAILURE);sleep(10);close(cli_fd);exit(EXIT_SUCCESS);
}/*****************************************************************************函 数 名  : setnonblocking功能描述  : 将参数所指的fd设置为非阻塞输入参数  : int fd  输出参数  : 无返 回 值  : int失败退出程序,成功返回fd的旧标志调用函数  : 被调函数  : 修改历史      :1.日    期   : 2019年12月23日作    者   : 江南_董少修改内容   : 新生成函数*****************************************************************************/
int setnonblocking(int fd)
{int old_options=fcntl(fd,F_GETFL);int new_options=old_options|O_NONBLOCK;if(fcntl(fd,F_SETFL,new_options)==-1){perror("fcntl");exit(EXIT_FAILURE);}return old_options;
}/*****************************************************************************函 数 名  : set_nonblocking_connect功能描述  : 输入参数  : const char* ip  int port        int time        输出参数  : 无返 回 值  : int调用函数  : 被调函数  : 修改历史      :1.日    期   : 2019年12月23日作    者   : 江南_董少修改内容   : 新生成函数*****************************************************************************/
int set_nonblocking_connect(const char* ip,const char* port,int time)
{int sock_fd,old_options,ret_val;struct sockaddr_in serAddress;//socketif((sock_fd=socket(AF_INET,SOCK_STREAM,0))==-1){perror("socket");exit(EXIT_FAILURE);}//set nonblockold_options=setnonblocking(sock_fd);//init addressbzero(&serAddress,sizeof(serAddress));serAddress.sin_family=AF_INET;serAddress.sin_port=htons(atoi(port));if(inet_pton(AF_INET,ip,&serAddress.sin_addr.s_addr)==-1){perror("inet_pton");exit(EXIT_FAILURE);}//connect//nonblocking connect success,return sock_fdif((ret_val=connect(sock_fd,(struct sockaddr*)&serAddress,sizeof(serAddress)))==0){printf("connect with server suucess\n");//set fd block and returnif(fcntl(sock_fd,F_SETFL,old_options)==-1){perror("fcntl");exit(EXIT_FAILURE);}return sock_fd;}//nonblocking connect errorelse if(errno!=EINPROGRESS){printf("unblock connect not support\n");return -1;}fd_set readfds;fd_set writefds;struct timeval timeout;FD_ZERO(&readfds);FD_ZERO(&writefds);timeout.tv_sec=time;timeout.tv_usec=0;ret_val=select(sock_fd+1,NULL,&writefds,NULL,&timeout);if(ret_val<=0){//select error or timeout,returnprintf("connection time out\n");close(sock_fd);return -1;}//nonblocking connect fd is not ready write,returnif(!FD_ISSET(sock_fd,&writefds)){printf("no events on sock_fd found\n");close(sock_fd);return -1;}int error=0;socklen_t length=sizeof(error);//get error and save to errorif(getsockopt(sock_fd,SOL_SOCKET,SO_ERROR,&error,&length)==-1){perror("getsockopt");exit(EXIT_FAILURE);}//error is not 0,meaning connect errorif(error!=0){printf("connect failed after select with the error:%d\n",error);close(sock_fd);return -1;}//connect successprintf("connect ready after select with the socket:%d\n",sock_fd);//set fd block and returnfcntl(sock_fd,F_SETFL,old_options);return sock_fd;
}

测试①

  • 我们使用程序去连接8888端口的服务器,但是服务器未开启,select等待10秒之后超时退出

测试②

  • 这个测试中,我们的服务器开启了8888监听端口
  • 我们客户端程序connect没有执行成功,但是返回了EINPROGRESS错误。于是在后面的select中等待非阻塞connect建立成功并且客户端fd变为可写的。接着消除错误编码并打印相关提示信息

Linux(程序设计):55---非阻塞connect(EINPROGRESS)相关推荐

  1. linux网络编程-----非阻塞connect

    libevent在内部由于使用io多路复用函数进行的事件监控,所以它所有的io读写操作都是非阻塞的,换句话说,libevent提供的接口函数evconnlistener_new_bind()和buff ...

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

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

  3. 由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?

    一般情况下,我们像下面代码中所示的这样使用非阻塞connect: #include <stdio.h> #include <stdlib.h> #include <str ...

  4. 【网络编程】非阻塞connect详解

    一.为什么使用非阻塞connect TCP连接的建立涉及一个在三路握手过程,阻塞的connect一直等到客户收到自己的SYN的ACK才返回,这需要至少一个RTT时间,RTT时间波动很大从几毫秒到几秒. ...

  5. 网络编程学习笔记(非阻塞connect)

    设置非阻塞,如果返回EINPROGRESS,表示正在建立连接,还没有完成 非阻塞的三个用途: 1.我们可以在三路握手的同时做其它的处理.connect要花一个往返时间完成,而且可以是在任何地主,从几个 ...

  6. 非阻塞connect的实现

    步骤1: 设置非阻塞,启动连接 实现非阻塞 connect ,首先把 sockfd 设置成非阻塞的.这样调用 connect 可以立刻返回,根据返回值和 errno 处理三种情况: (1) 如果返回 ...

  7. Linux 非阻塞connect,错误码:EINPROGRESS

    当我们以非阻塞的方式来进行连接的时候,返回的结果如果是 -1,这并不代表这次连接发生了错误,如果它的返回结果是 EINPROGRESS,那么就代表连接还在进行中. 后面可以通过poll或者select ...

  8. Linux高性能服务器I/0高级应用:非阻塞connect(15)

    前言 首linux系统下,connect函数是阻塞的,阻塞时间的长度与系统相关.而如果把套接字设置成非阻塞,调用connect函数时会报错Operation now in progress,且errn ...

  9. 非阻塞connect,错误码:EINPROGRESS

    当我们以非阻塞的方式来进行连接的时候,返回的结果如果是 -1,这并不代表这次连接发生了错误,如果它的返回结果是 EINPROGRESS,那么就代表连接还在进行中. 后面可以通过poll或者select ...

  10. 非阻塞connect

    在 socket 是阻塞模式下 connect 函数会一直到有明确的结果才会返回(或连接成功或连接失败),如果服务器地址"较远",连接速度比较慢,connect 函数在连接过程中可 ...

最新文章

  1. 实验探究 ioremap
  2. 代码编辑器揭露性格,你是哪一种?
  3. centos5.8安装mysql_Centos5.8上面用Shell脚本一键安装mysql5.5.25源码包
  4. mysql 授权truncate_有没有办法在MySQL中的TRUNCATE或DROP TABLE上有效地进行GRANT?
  5. Mybatis查询传递单个参数和传递多个参数用法
  6. 欢乐纪中A组赛【2019.8.17】
  7. java中的位移运算符_java中的移位运算符(, , )
  8. 山峰和山谷(信息学奥赛一本通-T1454)
  9. python对日期型数据排序_如何对日期执行数学运算并用Python对它们进行排序?
  10. Ganglia 权威指南-安装Ganglia过程
  11. Ultrabook是什么意思
  12. 机器学习 之 客户分群案例
  13. 使用python的sklearn包实现CCA(典型相关分析)
  14. 软件人员kpi制定模板_员工绩效考核制度模板(餐厅绩效考核方案制定)
  15. 走近Palantir
  16. Unity实现在白板上绘画涂鸦
  17. web前端设计师需要常去的15个设计博客资源站
  18. 《人生的智慧》-叔本华著[韦启昌-(译)]
  19. 持久化模型_建立领域模型-持久性不可知论简介
  20. 5xx 系列内部服务器错误

热门文章

  1. LaTeX论文自动化排版
  2. 可汗学院统计学笔记(二)
  3. xml与java对象互转
  4. 如何批量复制word文件名到excel?
  5. catkin翻译计算机,catkin是什么意思_catkin怎么读_catkin翻译_用法_发音_词组_同反义词_葇荑花(如柳絮等)-新东方在线英语词典...
  6. 眼睛里招人恼怒的“蚊子”,可以用眼药水治疗吗?
  7. 分库分表之淘宝TDDL的原理
  8. PCL源码剖析之MarchingCubes算法
  9. HBase与MapReduce
  10. win10下openface快速安装与使用