下连接超时的一种实覆盖

2021-08-24 淮安装修公司

实际运行结果如下:

xiaosuo@gentux perl $ ./t 10.16.101.1 90

timeout

xiaosuo@gentux perl $ ./t 10.16.101.1 90 1

timeout

可以看到,以上代码工作的很好,并且如果你想知道连接发生错误时的确切信息的话,你可以用getsocketopt获得:

int error;

socklen_t errorlen = sizeof(error);

getsockopt(fd, SOL_SOCKET, SO_ERROR, error, errorlen);

但是多少有些复杂,如果有象SO_SNDTIMO/SO_RCVTIMO一样的套接字参数可以让超时操作跳过select的话,世界将变得更美好。当然你还可以选用象apr一样提供了简单接口的库,但我这里要提的是另一种方法。

呵呵,引子似乎太长了点儿。读Linux内核源码的时候偶然发现其connect的超时参数竟然和用SO_SNDTIMO操作的参数一致:

File: net/ipv4/af_inet.c

559 timeo = sock_sndtimeo(sk, flags O_NONBLOCK);

河北和周边几个省份的人口数量都是全国的人口大省 560

561 if ((1 sk-sk_state) (TCPF_SYN_SENT | TCPF_SYN_RECV)) {

562 /* Error code is set above */

563 if (!timeo || !inet_wait_for_connect(sk, timeo))

564 goto out;

565

566 err = sock_intr_errno(timeo);

567 if (signal_pending(current))

568 goto out;

569 }

这意味着:在Linux平台下,可以通过在connect之前设置SO_SNDTIMO来达到控制连接超时的目的。简单的写了份测试代码:

#include stdlib.h

#include stdio.h

#include sys/types.h

#include sys/socket.h

#include netinet/in.h

#include errno.h

int main(int argc, char *argv[])

{

int fd;

struct sockaddr_in addr;

struct timeval timeo = {3, 0};

socklen_t len = sizeof(timeo);

fd = socket(AF_INET, SOCK_STREAM, 0);

if (argc == 4)

_sec = atoi(argv[3]);

setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, timeo, len);

n_family = AF_INET;

n_addr.s_addr = inet_addr(argv[1]);

n_port = htons(atoi(argv[2]));

if (connect(fd, (struct sockaddr*)addr, sizeof(addr)) == -1) {

if (errno == EINPROGRESS) {

fprintf(stderr, \"timeout\\n\");

return -1;

}

perror(\"connect\");

return 0;

}

printf(\"connected\\n\");

return 0;

}

执行结果:

xiaosuo@gentux perl $ ./t 10.16.101.1 90

timeout

xiaosuo@gentux perl $ ./t 10.16.101.1 90 2

timeout

和设想完全一致!

氨氯地平贝那普利片多少钱一盒
南京治白癜风医院
湖南治疗白癜风哪家医院好
为你推荐