Esempio n. 1
0
/**
* connect_timeout - connect
* @fd: 套接字
* @addr: 要连接的对方地址
* @wait_seconds: 等待超时秒数,如果为0表示正常模式
* 成功(未超时)返回0,失败返回-1,超时返回-1并且errno = ETIMEDOUT
*/
int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds)
{
        int ret;
        socklen_t addrlen = sizeof(struct sockaddr_in);

        if (wait_seconds > 0)
                activate_nonblock(fd);

        ret = connect(fd, (struct sockaddr*)addr, addrlen);
        if (ret < 0 && errno == EINPROGRESS)
        {
                fd_set connect_fdset;
                struct timeval timeout;
                FD_ZERO(&connect_fdset);
                FD_SET(fd, &connect_fdset);
                timeout.tv_sec = wait_seconds;
                timeout.tv_usec = 0;
                do
                {
                        /* 一量连接建立,套接字就可写 */
                        ret = select(fd + 1, NULL, &connect_fdset, NULL, &timeout);
                } while (ret < 0 && errno == EINTR);
                if (ret == 0)
                {
                        ret = -1;
                        errno = ETIMEDOUT;
                }
                else if (ret < 0)
                        return -1;
                else if (ret == 1)
                {
                        /* ret返回为1,可能有两种情况,一种是连接建立成功,一种是套接字产生错误,*/
                        /* 此时错误信息不会保存至errno变量中,因此,需要调用getsockopt来获取。 */
                        int err;
                        socklen_t socklen = sizeof(err);
                        int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &socklen);
                        if (sockoptret == -1)
                        {
                                return -1;
                        }
                        if (err == 0)
                        {
                                ret = 0;
                        }
                        else
                        {
                                errno = err;
                                ret = -1;
                        }
                }
        }
        if (wait_seconds > 0)
        {
                deactivate_nonblock(fd);
        }
        return ret;
}
int
connect_timeout(int sockfd,const struct sockaddr *addr,
			socklen_t addrlen,int tval)
{
	int ret = 0;
	if(tval > 0) {
		//这里首先进行connect操作,然后是
		//定时看连接是否超时,如果不超时就可以写了
		//所以不能阻塞到连接成功,
		//而应该通过select来定时判断是否连接成功
		activate_nonblock(sockfd);
	}
	ret = connect(sockfd,(struct sockaddr *)addr,addrlen);
	if(ret < 0 && EINPROGRESS == errno) {
		fd_set connect_fdset;
		struct timeval timeout;
		timeout.tv_sec = tval;
		timeout.tv_usec = 0;
		FD_ZERO(&connect_fdset);
		FD_SET(sockfd,&connect_fdset);
		do {
			ret = select(sockfd + 1,NULL,&connect_fdset,NULL,&timeout);
		} while(ret < 0 && EINTR == errno);
		if(0 == ret) {
			//timeout
			errno = ETIMEDOUT;
			ret = -1;
		} else if(ret < 0) {
			return ret;
		} else {
			//这里返回有两种情况,要么是连接成功,要么连接失败,
			//但是连接失败不会在select中以错误的方式返回
			//所以需要再次使用getsockopt来进行近一步的判断
			int err;
			socklen_t socklen = sizeof(err);
			int sockoptret = getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&err,&socklen);
			if(-1 == sockoptret) {
				return sockoptret;
			}
			if(0 == err) {
				ret = 0;
			} else {
				errno = err;
				ret = -1;
			}
		}
	}
	//要恢复阻塞的状态
	if(tval > 0) {
		deactivate_nonblock(sockfd);
	}
	return ret;
}
Esempio n. 3
0
int connect_timeout(int fd, struct sockaddr *addr, unsigned int wait_seconds)
{
    int ret = 0;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    if(wait_seconds > 0)
        activate_nonblock(fd);
    ret = connect(fd, (struct sockaddr *)addr, addrlen);
    if(ret == -1 && errno == EINPROGRESS)
    {
        fd_set connect_fdset;
        FD_ZERO(&connect_fdset);
        FD_SET(fd, &connect_fdset);
        struct timeval timeout;
        timeout.tv_sec = wait_seconds;
        timeout.tv_usec = 0;
        do{
            ret = select(fd+1, NULL, &connect_fdset, NULL, &timeout);
        }while(ret == -1 && errno == EINTR);
        if(ret == 0){
            ret = -1;
            errno = ETIMEDOUT;
        }else if(ret < 0){
            ret = -1;
        }else if(ret == 1){
            int err;
            socklen_t socklen = sizeof(err);
            int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &socklen);
            if(sockoptret == -1){
                return -1;
            }else if(err == 0){
                ret = 0;
            }else{
                errno = err;
                ret = -1;
            }
        }

    }
    if(wait_seconds > 0){
        deactivate_nonblock(fd);
    }
    return ret;
}
Esempio n. 4
0
/*
 * 函数名:connect_timeout
 * 描述:客服端接受数据
 * 参数:
 *
 * 返回:
 * */
int connect_timeout(int fd, struct sockaddr_in *addr,
		unsigned int wait_seconds)
{
	int ret;
	//获取socket结构体的大小。
	socklen_t addrlen = sizeof(struct sockaddr_in);
	//如果传入的等待时间大于0就取消socket的阻塞状态,0则不执行。
	if (wait_seconds > 0)
		activate_nonblock(fd);
	//链接
	/*
	 * int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
	 *
	 * */
	ret = connect(fd, (struct sockaddr*) addr, addrlen);
	//EINPROGRESS 正在处理
	if (ret < 0 && errno == EINPROGRESS)
	{
		/*
		 * void FD_CLR(int fd, fd_set *set);
		 * int  FD_ISSET(int fd, fd_set *set);
		 * void FD_SET(int fd, fd_set *set);
		 * void FD_ZERO(fd_set *set);
		 * */
		//设置监听集合
		fd_set connect_fdset;
		struct timeval timeout;
		//初始化集合
		FD_ZERO(&connect_fdset);
		//把fd 文件描述符的socket加入监听集合
		FD_SET(fd, &connect_fdset);
		/*
		 * struct timeval {
		 *     long    tv_sec;         // seconds       秒
		 *     long    tv_usec;        // microseconds  微妙
		 *     };
		 * */
		timeout.tv_sec = wait_seconds;
		timeout.tv_usec = 0;
		do
		{
			// 一但连接建立,则套接字就可写  所以connect_fdset放在了写集合中
			ret = select(fd + 1, NULL, &connect_fdset, NULL, &timeout);
		} while (ret < 0 && errno == EINTR);
		if (ret == 0)
		{
			ret = -1;
			/*
			 * #define ETIMEDOUT       110     // Connection timed out
             *  Tcp是面向连接的。在程序中表现为,当tcp检测到对端socket不再可
             *  用时(不能发出探测包,或探测包没有收到ACK的响应包),select会
             *  返回socket可读,并且在recv时返回-1,同时置上errno为ETIMEDOUT。
			 * */
			errno = ETIMEDOUT;
		} else if (ret < 0)
			return -1;
		else if (ret == 1)
		{
			//printf("22222222222222222\n");
			/* ret返回为1(表示套接字可写),可能有两种情况,一种是连接建立成功,一种是套接字产生错误,*/
			/* 此时错误信息不会保存至errno变量中,因此,需要调用getsockopt来获取。 */
			int err;
			socklen_t socklen = sizeof(err);
			//获取socket的状态
			int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err,
					&socklen);
			if (sockoptret == -1)
			{
				return -1;
			}
			if (err == 0)
			{
				ret = 0;
			} else
			{
				errno = err;
				ret = -1;
			}
		}
	}
	if (wait_seconds > 0)
	{
		deactivate_nonblock(fd);
	}
	return ret;
}
Esempio n. 5
0
/**
 * connect_timeout - connect
 * @fd: 套接字
 * @addr: 要连接的对方地址
 * @wait_seconds: 等待超时秒数,如果为0表示正常模式
 * 成功(未超时)返回0,失败返回-1,超时返回-1并且errno = ETIMEDOUT
 */
 int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds)
 {
 	int ret;
 	socklen_t addrlen = sizeof(struct sockaddr_in);

 	if (wait_seconds > 0)
 		activate_nonblock(fd);

 	ret = connect(fd, (struct sockaddr*)addr, addrlen);
 	if (ret < 0 && errno == EINPROGRESS)
 	{
        /*
 		fd_set connect_fdset;
 		struct timeval timeout;
 		FD_ZERO(&connect_fdset);
 		FD_SET(fd, &connect_fdset);
 		timeout.tv_sec = wait_seconds;
 		timeout.tv_usec = 0;
 		do
 		{
 			ret = select(fd + 1, NULL, &connect_fdset, NULL, &timeout);
 		} while (ret < 0 && errno == EINTR);
        */
        int epfd;
        epfd = epoll_create1(0);
        struct epoll_event evn;
        struct epoll_event *events = NULL;
        evn.data.fd = fd;
        evn.events = EPOLLOUT | EPOLLET;
        epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &evn);

        do{
        
            ret = epoll_wait(epfd, events, MAXEVENTS, wait_seconds);
        }while(ret < 0 && errno == EINTR);
 		if (ret == 0)
 		{
 			ret = -1;
 			errno = ETIMEDOUT;
 		}
 		else if (ret < 0)
 			return -1;
 		else if (ret == 1)
 		{
			/* ret返回为1,可能有两种情况,一种是连接建立成功,一种是套接字产生错误,*/
			/* 此时错误信息不会保存至errno变量中,因此,需要调用getsockopt来获取。 */
 			int err;
 			socklen_t socklen = sizeof(err);
 			int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &socklen);
 			if (sockoptret == -1)
 			{
 				return -1;
 			}
 			if (err == 0)
 			{
 				ret = 0;
 			}
 			else
 			{
 				errno = err;
 				ret = -1;
 			}
 		}
 	}
 	if (wait_seconds > 0)
 	{
 		deactivate_nonblock(fd);
 	}
 	return ret;
 }