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) |