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;
}