1. 程式人生 > >socket中connect的預設超時時間

socket中connect的預設超時時間

1.connect函式原型:

# include < sys/ types. h> /* See NOTES */
# include < sys/ socket . h>
int connect ( int sockfd, const struct sockaddr * serv_addr, socklen_t addrlen) ;

RETURN VALUE:
       If  the  connection  or  binding  succeeds,  zero  is  returned.   On error, -1 is returned, and errno is set appropriately.


 
2.預設情況下,connect函式的超時情況:
引用: http://blog.chinaunix.net/u1/53217/showart_710651.html  
《UNP》第一卷 第三版 P85-P86指出伯克利系統的超時時限為75s, Solaris9超時時限為4分鐘,所以一般認為是75s到幾分鐘不等,而我測試的時限為 189s(Linux Kernel 2.6.24),SYN6次重傳~~
我的FC8 Linux Kernel  2.6.23.1-42,測試超時時間為 189s

3.支援重試的連線(APUE2 16.4節)

#include < stdio.

h>
#include < stdlib. h>
#include < netinet/in . h>
#include < sys/socket. h>
#include < string. h>
#include < fcntl. h>

#define SRV_PORT 65530

#define MAXSLEEP 128

#define errexit( msg) do {perror( msg) ; exit( EXIT_FAILURE) ; } while ( 0)

/* * *
 * max sleep
time = 1 + 2 + 4 + 8 + 18 + . . . + 64 = 2^7 - 1 = 127 ( s)
 * * * /
int connect_retry( int sockfd, const struct sockaddr * srv_addr, socklen_t addrlen)
{
        int nsec;

        for ( nsec = 1; nsec < = MAXSLEEP; nsec < < = 1)
        {
                if ( connect( sockfd, srv_addr, addrlen) = = 0)
                        return 0; /* connection accepted * /
                if ( nsec < = MAXSLEEP / 2) /* < = 2^7 /2 = 64* /
                        sleep ( nsec) ;
        }

        return - 1

}

int main( int argc, char * argv[ ] )
{
        int sockfd;
        struct sockaddr_in srv_addr;
        socklen_t addrlen;

        int flags;

        if ( argc ! = 2) {
                printf( "Usage: %s <ip>/n" , argv[ 0] ) ;
                exit( 1) ;
        }

        if ( ( sockfd = socket( AF_INET, SOCK_STREAM, 0) ) < 0)
                errexit( "socket error" ) ;

        addrlen = sizeof ( struct sockaddr) ;
        memset( & srv_addr, 0, addrlen) ;
        srv_addr. sin_family = AF_INET;
        srv_addr. sin_addr. s_addr = inet_addr( argv[ 1] ) ;
        srv_addr. sin_port = htons( SRV_PORT) ;

        flags = fcntl( sockfd, F_GETFL, 0) ;
        fcntl( sockfd, F_SETFL, flags | O_NONBLOCK) ;

        printf( "connecting.../n" ) ;
        time_t t = time( NULL) ;
        //if ( connect( sockfd, ( struct sockaddr * ) & srv_addr, addrlen) < 0) {
        if ( connect_retry( sockfd, ( struct sockaddr * ) & srv_addr, addrlen) < 0) {
                printf( "interval = %d/n" , time( NULL) - t) ;

                close(sockfd);
                errexit( "connect error" ) ;
        }
        close(sockfd);

       exit( 0) ;
}


說明:

1. 在阻塞情況下,connect函式在 Linux Kernel  2.6.23.1-42,測試超時時間為 189s。

2. 在用上述方法設定的非阻塞情況下,connect_retry 函式中,如果呼叫connect失敗,程序就會休眠一小段時間然後在嘗試連線,每迴圈一次增加每次嘗試的延遲, 直到最大延遲為 127s。