happyj2me
4/22/2019 - 9:21 AM

connect_timeout

int connect_timeout(int sockfd, const struct sockaddr *addr,
                    socklen_t addrlen, struct timeval *timeout) 
{
    int flags = fcntl( sockfd, F_GETFL, 0 );
    if (flags == -1) {
	return -1;
    }
    if (fcntl( sockfd, F_SETFL, flags | O_NONBLOCK ) < 0) {
	return -1;
    }
    
    int status = connect(sockfd, addr, addrlen);
    if (status == -1 and errno != EINPROGRESS) {
	return -1;
    }
    if (status == 0) {
	if (fcntl(sockfd, F_SETFL, flags) <  0) {
	    return -1;
	}
	return 1;
    }
    fd_set read_events;
    fd_set write_events;
    FD_ZERO(&read_events);
    FD_SET(sockfd, &read_events);
    write_events = read_events;
    int rc = select(sockfd + 1, &read_events, &write_events, nullptr, timeout );
    if (rc < 0) {
	return -1;
    } else if (rc == 0) {
	return 0;
    }
    if (!isconnected(sockfd, &read_events, &write_events) )
    {
	return -1;
    }
    if ( fcntl( sockfd, F_SETFL, flags ) < 0 ) {
	return -1;
    }
    return 1;
}
bool isconnected(int sockfd, fd_set *rd, fd_set *wr)
{
    if (!FD_ISSET(sockfd, rd) && !FD_ISSET(sockfd, wr)) {
	return false;
    }
    
    //发生错误了或者connect和select之间来了数据,都是可读可写的,要作区分
    int err;
    socklen_t len = sizeof(err);
    if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
	return false;
    }
    errno = err;		/* in case we're not connected */
    return err == 0;
}