Skip to content

Instantly share code, notes, and snippets.

@tai2
Created July 25, 2011 17:13
Show Gist options
  • Save tai2/1104608 to your computer and use it in GitHub Desktop.
Save tai2/1104608 to your computer and use it in GitHub Desktop.
connect system call with blocking timeout.
// 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