(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。