关于tcp连接的异步connect实现流程如下:
(1)设置socket连接为NONBLOCK
(2)调用connect函数
(3)poll函数检测fd
(4)判断poll函数的返回值来确定连接是否建立
下面是一个测试代码。
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <poll.h>
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <netinet/ip.h>
-
#include <netinet/tcp.h>
-
#include <fcntl.h>
-
#include <errno.h>
-
#include <strings.h>
-
#include <string.h>
-
int main(int argc, char **argv)
-
{
-
int old;
-
int err;
-
int errlen = sizeof(err);
-
struct sockaddr_in addr;
-
socklen_t len = sizeof(struct sockaddr_in);
-
int timeo;
-
int fd;
-
struct pollfd pfd;
-
int ret;
-
-
if (argc != 4) {
-
printf("Usage %s ip port timeout\n", argv[0]);
-
return -1;
-
}
-
timeo = atoi(argv[3]);
-
fd = socket(AF_INET, SOCK_STREAM, 0);
-
if (fd < 0) {
-
printf("Create socket error erno=%d : %s\n", errno,strerror(errno));
-
return -1;
-
}
-
-
bzero(&addr, sizeof(addr));
-
addr.sin_family = AF_INET;
-
addr.sin_addr.s_addr = inet_addr(argv[1]);
-
addr.sin_port = htons(atoi(argv[2]));
-
-
old = fcntl(fd, F_GETFL, 0);
-
if (fcntl(fd, F_SETFL, old|O_NONBLOCK) < 0) {
-
printf("setting fd error: errno,%s\n", errno,strerror(errno));
-
close(fd);
-
return -1;
-
}
-
-
if (connect(fd, (struct sockaddr*)&addr, len) == -1 &&
-
errno != EINPROGRESS) {
-
printf("Error in connect: %d,%s\n", errno,strerror(errno));
-
close(fd);
-
return -1;
-
}
-
-
pfd.fd = fd;
-
pfd.events = POLLOUT | POLLERR | POLLHUP | POLLNVAL;
-
errno = 0;
-
-
if (timeo <= 0)
-
timeo = -1;
-
-
ret = poll(&pfd, 1, timeo);
-
-
if (ret < 0) {
-
if (errno == EINTR) {
-
close(fd);
-
return -1;
-
}
-
close(fd);
-
return -1;
-
-
} else if (0 == ret) {
-
close(fd);
-
return -1;
-
}
-
-
if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
-
close(fd);
-
return -1;
-
}
-
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, (socklen_t*)&errlen) == -1) {
-
close(fd);
-
return -1;
-
}
-
if (err != 0) {//check the SO_ERROR state
-
errno = err;
-
close(fd);
-
return -1;
-
}
-
-
fcntl(fd, F_SETFL, old);
-
printf("Connect real OK\n");
-
return fd;
-
}
在这个代码,如果传入的超时时间小于等于0,那么poll会一直等待。
但是要注意的是,这里所谓的一直等待,绝对不是无限期等下去,具体等待时间与系统配置参数有关。
比如你连接的目的地址不存在,那么syn最多重试发送net.ipv4.tcp_syn_retries次后就会返回POLLERR。
阅读(17370) | 评论(0) | 转发(0) |