Created
July 25, 2011 17:13
-
-
Save tai2/1104608 to your computer and use it in GitHub Desktop.
connect system call with blocking timeout.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// connect system call with blocking timeout. | |
#include <sys/socket.h> | |
#include <sys/select.h> | |
#include <sys/time.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
int | |
connect_with_timeout(int addr_v4, unsigned int port, int timeout) | |
{ | |
int sock = -1; | |
struct sockaddr_in server = {0}; | |
struct timeval tv; | |
int flags, n, error; | |
fd_set rset, wset; | |
socklen_t len; | |
sock = socket(PF_INET, SOCK_STREAM, 0); | |
if (sock == -1) { | |
goto error; | |
} | |
// set the socket to nonblocking mode. | |
flags = fcntl(sock, F_GETFL, 0); | |
if (flags != -1) { | |
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) { | |
goto error; | |
} | |
} else { | |
goto error; | |
} | |
// connect | |
server.sin_family = PF_INET; | |
server.sin_addr.s_addr = htonl(addr_v4); | |
server.sin_port = htons(port); | |
n = connect(sock, (struct sockaddr*)&server, sizeof(server)); | |
if (n == -1) { | |
if (errno == EINPROGRESS) { | |
FD_ZERO(&rset); | |
FD_SET(sock, &rset); | |
wset = rset; | |
tv.tv_sec = timeout / 1000; | |
tv.tv_usec = (timeout % 1000) * 1000; | |
n = select(sock + 1, &rset, &wset, NULL, timeout ? &tv : NULL); | |
if (n == -1) { | |
goto error; | |
} else if (n == 0) { | |
// timeout | |
goto error; | |
} | |
if (FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)) { | |
error = 0; | |
len = sizeof(error); | |
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) == -1) { | |
goto error; | |
} | |
if (error) { | |
goto error; | |
} | |
} else { | |
goto error; | |
} | |
} else { | |
goto error; | |
} | |
} | |
// recover the socket state. | |
if (fcntl(sock, F_SETFL, flags) == -1) { | |
goto error; | |
} | |
return 0; | |
error: | |
if (sock != -1) { | |
close(sock); | |
} | |
return -1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment