zoukankan      html  css  js  c++  java
  • accpet和connect设置超时

    三次握手

    TCP连接建立的开始是三次握手,通过三次交互确认连接成功,在客户端调用connect时,客户端发送sync消息给服务端,服务端收到sync消息后,返回一个ack+sync,并等待ack,客户端收到ack+sync后,返回一个ack,connect返回,服务端收到ack后,accept返回,如下图所示:


    connect超时设置

    如果connect连接的服务端不存在,或是异常了,会出现什么情况,可能有以下几种情况:

    • 服务端返回连接错误

    • 等待系统默认的75秒超时

    上述两种情况都是不可控的,因此可以通过设置超时时间的方式控制超时时间,有下述两种方法。

    非阻塞connect+select

    将conenct设置成非阻塞后,connect在发送sync后直接返回-1,然后使用select等待ack+sync,select是可以设置超时时间,因此达到设置超时时间的目的。注意需要将socket恢复成阻塞模式,如下所示:

    dwSign = 1;
    if((err = ioctl(socket, FIONBIO, &dwSign)) < 0)
    {
        printf("ioctl socket failed, errno = %d!
    ", err);  
        close(socket);
        return err;
    }
    
    SOCKADDR_IN tServerAddrInfo = {0};
    tServerAddrInfo.sin_family       = AF_INET;
    tServerAddrInfo.sin_addr.s_addr  = ServerIP;
    tServerAddrInfo.sin_port         = ServerPort;
    int bRet = 0x0;
    fd_set set = {0x0};
    if(-1 == connect(socket, (SOCKADDR*)&tServerAddrInfo, sizeof(SOCKADDR)))
    {
        tm.tv_sec = 10;
        tm.tv_usec = 0;
        FD_ZERO(&set);
        FD_SET(socket, &set);
        
        // select返回值大于0,表示有数据可以操作;select返回值等于0,表示超时
        if(select(socket + 1, NULL, &set, NULL, &tm) > 0)
        {
            // 获取socket的error值,0表示成功
            getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
            if(error == 0)
            {
                bRet = TRUE;
            }
            else
            {
                bRet = FALSE;
            }
        }
        else
        {
            bRet = FALSE;
        }
    }
    else
    {
        bRet = TRUE;
    }
    
    dwSign = 0;
    if(0 > (err = ioctl(socket, FIONBIO, &dwSign)))
    {
        printf("ioctl socket failed, errno = %d!
    ", err);  
        close(dwSocket);    
        return err;
    }

     设置socket的发送超时时间

    调用connect函数实际上是发送sync报文,如果设置发送超时时间,那么也就可以实现connect的超时时间,如下所示:

    struct timeval timeout = {10, 0);
    setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval));

    accpet超时设置

    既然可以通过设置发送超时时间,控制connect的超时时间,那么同理,也可以通过设置接收超时时间来设置accept的超时时间,如下所示:

    struct timeval timeout = {10, 0};
    setsockopt(proxy_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
  • 相关阅读:
    BestCoder Round #67 (div.2) N bulbs(hdu 5600)
    蓝桥杯 基础练习 特殊回文数
    蓝桥杯 基础练习 十进制转十六进制
    蓝桥杯 基础练习 十六进制转十进制
    蓝桥杯 基础练习 十六进制转八进制
    蓝桥杯 入门训练 Fibonacci数列
    Codeforces 600B Queries about less or equal elements(二分查找)
    Codeforces Round #332 (Div. 二) B. Spongebob and Joke
    Codeforces Wilbur and Array
    UVA 10129-Play on Words(欧拉通路)
  • 原文地址:https://www.cnblogs.com/chusiyong/p/12148845.html
Copyright © 2011-2022 走看看