我们用man connection命令查看手册,如下:
 
  1. EINPROGRESS
  2. The socket is nonblocking and the connection cannot be completed immediately. It
  3. is possible to select(2) or poll(2) for completion by selecting the socket for
  4. writing. After select(2) indicates writability, use getsockopt(2) to read the
  5. 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
  6. codes listed here, explaining the reason for the failure).
当connect可写时还可能是发生了错误,我们必须判断这种情况。发生错误时套接字既可读又可写,而connect连接成功时套接字也可能即可读又可写(select之前有可能连接已经建立并有来自对端的数据到达).
 
如何区分这两种情况呢?因此,必须调用

  1. getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len)

另一个问题,对于非阻塞式套接字,如果其上的connect调用被信号中断并且不会由内核自动重启,那么它将返回EINTR,此时我们不能再次调用connect等待未完成的连接继续完成,这样做将导致返回EADDRINUSE错误。我们只能调用select检测其状态,就像上面说的那样。

 
 
int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds)
{
int ret;
socklen_t addrlen = sizeof(struct sockaddr_in); if (wait_seconds > 0)
activate_nonblock(fd); //设为非阻塞 ret = connect(fd, (struct sockaddr*)addr, addrlen);
if (ret < 0 && errno == EINPROGRESS)
{
//printf("11111111111111111111\n");
fd_set connect_fdset;
struct timeval timeout;
FD_ZERO(&connect_fdset);
FD_SET(fd, &connect_fdset);
timeout.tv_sec = wait_seconds;
timeout.tv_usec = 0;
do
{
// 一但连接建立,则套接字就可写 所以connect_fdset放在了写集合中
ret = select(fd + 1, NULL, &connect_fdset, NULL, &timeout);
} while (ret < 0 && errno == EINTR);
if (ret == 0)
{
ret = -1;
errno = ETIMEDOUT;
}
else if (ret < 0)
return -1;
else if (ret == 1)
{
//printf("22222222222222222\n");
/* ret返回为1(表示套接字可写),可能有两种情况,一种是连接建立成功,一种是套接字产生错误,*/
/* 此时错误信息不会保存至errno变量中,因此,需要调用getsockopt来获取。 */
int err;
socklen_t socklen = sizeof(err);
int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &socklen);
if (sockoptret == -1)
{
return -1;
}
if (err == 0)
{
//printf("3333333333333\n");
ret = 0;
}
else
{
//printf("4444444444444444:%d\n", err);
errno = err;
ret = -1;
}
}
}
if (wait_seconds > 0)
{
deactivate_nonblock(fd); //设回阻塞
}
return ret;
}

  

关于非阻塞connect的若干细节性问题的更多相关文章

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

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

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

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

  3. (转)非阻塞Connect对于select时应注意问题

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

  4. UNIX网络编程——非阻塞connect:时间获取客户程序

    #include "unp.h" int connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec) ...

  5. UNIX网络编程——非阻塞connect

    当在一个非阻塞的TCP套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的TCP三次握手继续进行.我们接着使用select检测这个连接或成功或失败的已建 ...

  6. TCP之非阻塞connect和accept

    套接字的默认状态是阻塞的,这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待响应操作完成,可能阻塞的套接字调用可分为以下四类: (1) 输入操作,包括read,readv,rec ...

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

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

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

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

  9. 非阻塞connect

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

随机推荐

  1. [Virtualization][SDN] VXLAN到底是什么 [转]

    写在转发之前: 几个月以前,在北大机房和燕园大厦直接拉了一根光钎.两端彼此为校园内公网IP.为了方便连接彼此机房,我做个一个VPN server在燕园的边界,北大机房使用client拨回.两个物理机房 ...

  2. ngios

    一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报 ...

  3. HBase的安装部署以及简单使用

    一:下载安装 1.下载安装 2.开启hadoop与zookeeper 3.修改配置文件hbase-env export JAVA_HOME=/opt/modules/jdk1.7.0_67 expor ...

  4. JVM内存状况查看方法和分析工具-jmap

    jmap -heap 27657 Attaching to process ID 27657, please wait... Debugger attached successfully. Serve ...

  5. Android Handler简单示例

    package com.firstapp.foo.firstapp; import android.os.Handler; import android.os.Message; import andr ...

  6. Nodejs电影建站开发实例(下)

    作为一个真正的网站,不能没有数据的支持,下面使用的数据库为mongodb,电影可能有的数据:电影名称.导演.国家.语言.上映时间.图片.简介.视频 4.使用路由 app.js var express ...

  7. ArcGIS Engine开发之旅03--ArcGIS Engine中的控件

    原文:ArcGIS Engine开发之旅03--ArcGIS Engine中的控件 制图控件,如MapControl.PageLayoutControl,其中MapControl控件主要用于地理数据的 ...

  8. oracle入门-%的用法

    vempno emp.empno%type; 例如上面的这句话,你的vempno就是你定义的变量,和面的那个emp是你数据库里面存在的表,他的表里面有意个empno字段,然后%type就是empno的 ...

  9. c#上传文件(一)使用 .net 控件上传文件

    1.html代码: <body> <form id="form1" runat="server"> <div> <as ...

  10. mysql学习笔记——支持存储引擎