转自:庖丁解牛

/**
* connect_timeout - 带超时的connect(方法中已执行connect)
* @fd:文件描述符
* @addr:地址结构体指针
* @wait_seconds:等待超时秒数,如果为0表示不检测超时
* 成功返回0.失败返回-1,超时返回-1并且errno = ETIMEDOUT
* */
int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds)
{
    int ret = 0;
    //connect()函数是连接服务器,本来connect会阻塞,但是设置未阻塞之后,
    //客户端仍然会三次握手机制,如果三次握手失败,那么客户端一定无法向文件描述符中写入数据
    //如果连接成功,那么客户端就可以向文件描述符写入数据了,
    //所以交给select监管的文件描述符如果可以写,说明连接成功,不可以写说明连接失败

//设置当前文件描述符未阻塞--设置非阻塞之后,
    //connect在网络中非常耗时,所以需要设置成非阻塞,如果有读事件,说明可能连接成功
    //这样有利于做超时限制
    if (wait_seconds > 0)
    {
        if (activate_nonblock(fd) == -1)
            return -1;
    }
    ret = connect(fd, (struct sockaddr *) addr, sizeof(struct sockaddr));
    if (ret == -1 && errno == EINPROGRESS)
    {
        fd_set writefds;
        FD_ZERO(&writefds);
        FD_SET(fd, &writefds);
        struct timeval timeout;
        timeout.tv_sec = wait_seconds;
        timeout.tv_usec = 0;
        do
        {
            ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
        } while (ret == -1 && errno == EINTR);
        //ret==-1 不需要处理,正好给ret赋值
        //select()报错,但是此时不能退出当前connect_timeout()函数
        //因为还需要取消文件描述符的非阻塞
        if (ret == 0)
        {
            errno = ETIMEDOUT;
            ret = -1;
        } else if (ret == 1)
        {
            //ret返回为1(表示套接字可写),可能有两种情况,一种是连接建立成功,一种是套接字产生错误,
            //此时错误信息不会保存至errno变量中,因此,需要调用getsockopt来获取。
            int err = 0;
            socklen_t len = sizeof(err);
            ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
            if (ret == 0 && err != 0)
            {
                errno = err;
                ret = -1;
            }
            //说明套接字没有发生错误,成功
        }
    }
    if (wait_seconds > 0)
    {
        if (deactivate_nonblock(fd) == -1)
            return -1;
    }
    return ret;
}

ps:有人测试利用getsockopt方式判断连接建立成功与否在linux环境下不可用,如下方式:

connect(sock_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
int err = errno;
if  (err == EISCONN)
    {
         printf("connect finished 111.\n");
         ret = 0;
    }

connect设置连接超时的更多相关文章

  1. 转 HttpClient 设置连接超时时间

    要: HttpClient 4.5版本升级后,设置超时时间的API又有新的变化,请大家关注. HttpClient升级到4.5版本后,API有很多变化,HttpClient 4之后,API一直没有太稳 ...

  2. HttpClient设置连接超时时间

    https://www.cnblogs.com/winner-0715/p/7087591.html 使用HttpClient,一般都需要设置连接超时时间和获取数据超时时间.这两个参数很重要,目的是为 ...

  3. tcp中设置连接超时

    直接上代码: 设置连接超时 //首先改成非阻塞套接字 unsigned ; int rm=ioctl(sConnect,FIONBIO,(unsigned long*)&ul); ) { pr ...

  4. Retrofit2.0 设置 连接超时

    Retrofit2.0 这个网络请求框架使用了很久了,最近一次出现一个小插曲. 有一个接口,返回的数据量因为业务的原因 会返回很大的数据量,此时网络不大好的情况下,会出现请求失败的情况 也就是回调了 ...

  5. [转]c# winform tcp connect timeout 连接超时设置

    转自:https://www.cnblogs.com/jhlong/p/5622336.html 简单的c# TCP通讯(TcpListener) C# 的TCP Socket (同步方式) C# 的 ...

  6. SqlConnection 无法设置连接超时

    1.最有效的方法:对表格建立索引 2 在连接字符串中设置 Connection Timeout (默认15秒)3 设置 SqlCommand.CommandTimeout(默认是 30 秒)

  7. mysql设置连接超时时间参数:wait_timeout

    [root@ ~]# mysql -h 192.168.0.* -uroot -pEnter password: Welcome to the MySQL monitor. Commands end ...

  8. connect socket的超时设置

    最近项目中,有个需求是检测某ip地址是否是通的,使用了socket的connect函数.但是,当ip地址写错的话,connect就会一直阻塞在那里,大概2.3分钟才能返回连接失败.这对于用户来说是不可 ...

  9. HttpClient代理IP及设置连接读取超时

    1.不废话,上代码: public static void main(String[] args) throws Exception { CloseableHttpClient httpClient ...

随机推荐

  1. [Codeforces Round #508 (Div. 2)][Codeforces 1038E. Maximum Matching]

    前几天给舍友讲这题的时候感觉挺有意思的,就贴上来吧... 题目链接:1038E - Maximum Matching 题目大意:有\(n\)个棒子,每个条两端有颜色\(c1,c2\)以及他的价值\(v ...

  2. 全排列筛选(java)

    蓝桥杯-全排列筛选(java) 蓝桥杯每年必考全排列筛选,一般为填空题: 可以使用for循环暴力破解,但是代码相对较长,也比较乱,不建议使用: 这里使用递归来解决,代码量相对较少,也很好理解: 如下为 ...

  3. 一次Spring Bean初始化顺序问题排查记录

    最近在使用Springboot的时候需要通过静态的方法获取到Spring容器托管的bean对象,参照一些博文里写的,新建了个类,并实现ApplicationContextAware接口.代码大致如下: ...

  4. verilog 之流水灯

    1.黑金板 简易操作: 通过判断数值累加    个人观点:黑金代码质量有待提高,讲解不够详细 2.正点原子的 位置调换 led[:] <= {led[:],led[]}; 3.传统位移 led& ...

  5. Mac 下安装Fiddler抓包工具

    需求 我们都知道在Mac电脑下面有一个非常好的抓包工具:Charles.但是这个只能抓代理的数据包.但是有时候想要调试本地网卡的数据库 Charles 就没办法了.就想到了在windows下面的一个F ...

  6. 系统重启后,mr程序不生成当前时间段的MRx文件问题

    系统重启后,mr程序不生成当前时间段的MRx文件问题 2019-4-2 之前使用正常的MR程序,系统重启后无法生成MRE\MRO\MRS文件. 服务器有两个时钟:硬件时钟和系统时钟 硬件时钟从根本上讲 ...

  7. linux和shell的学习记录

    1.16条常用的命令 .文件的权限修改:(把文件1.txt的归属改为mysql的,然后ll查看) chown mysql:mysql .txt .增加当前用户的x权限,然后ll查看: chomd u+ ...

  8. jmeter 之 beanshell sample

    Lightweight Scripting for Java 官网:http://www.BeanShell.org/ 定时器: BeanShell Timer 前置处理器:BeanShell Pre ...

  9. 一对一关联模型,HAS_ONE

    class UserModel extends RelationModel{ protected $_link = array( 'Profile'=> HAS_ONE, //就这一行就行了 ) ...

  10. mysql统计库下所有表数据行数

    一.执行下面sql select concat( 'select "', TABLE_name, '", count(*) from ', TABLE_SCHEMA, '.', T ...