Chinaunix首页 | 论坛 | 博客
  • 博客访问: 350304
  • 博文数量: 60
  • 博客积分: 1570
  • 博客等级: 上尉
  • 技术积分: 620
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-02 23:37
文章分类

全部博文(60)

文章存档

2012年(2)

2010年(2)

2009年(56)

分类: LINUX

2009-11-12 18:40:55

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函数的超时情况:
《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 + 16 + ... + 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 \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。

 

阅读(3500) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~