C: socket connection timeout C: socket connection timeout c c

C: socket connection timeout


Set the socket non-blocking, and use select() (which takes a timeout parameter). If a non-blocking socket is trying to connect, then select() will indicate that the socket is writeable when the connect() finishes (either successfully or unsuccessfully). You then use getsockopt() to determine the outcome of the connect():

int main(int argc, char **argv) {    u_short port;                /* user specified port number */    char *addr;                  /* will be a pointer to the address */    struct sockaddr_in address;  /* the libc network address data structure */    short int sock = -1;         /* file descriptor for the network socket */    fd_set fdset;    struct timeval tv;    if (argc != 3) {        fprintf(stderr, "Usage %s <port_num> <address>\n", argv[0]);        return EXIT_FAILURE;    }    port = atoi(argv[1]);    addr = argv[2];    address.sin_family = AF_INET;    address.sin_addr.s_addr = inet_addr(addr); /* assign the address */    address.sin_port = htons(port);            /* translate int2port num */    sock = socket(AF_INET, SOCK_STREAM, 0);    fcntl(sock, F_SETFL, O_NONBLOCK);    connect(sock, (struct sockaddr *)&address, sizeof(address));    FD_ZERO(&fdset);    FD_SET(sock, &fdset);    tv.tv_sec = 10;             /* 10 second timeout */    tv.tv_usec = 0;    if (select(sock + 1, NULL, &fdset, NULL, &tv) == 1)    {        int so_error;        socklen_t len = sizeof so_error;        getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);        if (so_error == 0) {            printf("%s:%d is open\n", addr, port);        }    }    close(sock);    return 0;}


This article might help:

Connect with timeout (or another use for select() )

Looks like you put the socket into non-blocking mode until you've connected, and then put it back into blocking mode once the connection's established.

void connect_w_to(void) {   int res;   struct sockaddr_in addr;   long arg;   fd_set myset;   struct timeval tv;   int valopt;   socklen_t lon;   // Create socket   soc = socket(AF_INET, SOCK_STREAM, 0);   if (soc < 0) {      fprintf(stderr, "Error creating socket (%d %s)\n", errno, strerror(errno));      exit(0);   }   addr.sin_family = AF_INET;   addr.sin_port = htons(2000);   addr.sin_addr.s_addr = inet_addr("192.168.0.1");   // Set non-blocking   if( (arg = fcntl(soc, F_GETFL, NULL)) < 0) {      fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));      exit(0);   }   arg |= O_NONBLOCK;   if( fcntl(soc, F_SETFL, arg) < 0) {      fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));      exit(0);   }   // Trying to connect with timeout   res = connect(soc, (struct sockaddr *)&addr, sizeof(addr));   if (res < 0) {      if (errno == EINPROGRESS) {         fprintf(stderr, "EINPROGRESS in connect() - selecting\n");         do {            tv.tv_sec = 15;            tv.tv_usec = 0;            FD_ZERO(&myset);            FD_SET(soc, &myset);            res = select(soc+1, NULL, &myset, NULL, &tv);            if (res < 0 && errno != EINTR) {               fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));               exit(0);            }            else if (res > 0) {               // Socket selected for write               lon = sizeof(int);               if (getsockopt(soc, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {                  fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno));                  exit(0);               }               // Check the value returned...               if (valopt) {                  fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt) );                  exit(0);               }               break;            }            else {               fprintf(stderr, "Timeout in select() - Cancelling!\n");               exit(0);            }         } while (1);      }      else {         fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));         exit(0);      }   }   // Set to blocking mode again...   if( (arg = fcntl(soc, F_GETFL, NULL)) < 0) {      fprintf(stderr, "Error fcntl(..., F_GETFL) (%s)\n", strerror(errno));      exit(0);   }   arg &= (~O_NONBLOCK);   if( fcntl(soc, F_SETFL, arg) < 0) {      fprintf(stderr, "Error fcntl(..., F_SETFL) (%s)\n", strerror(errno));      exit(0);   }   // I hope that is all }


The answers about using select()/poll() are right and code should be written this way to be portable.

However, since you're on Linux, you can do this:

int synRetries = 2; // Send a total of 3 SYN packets => Timeout ~7ssetsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &synRetries, sizeof(synRetries));

See man 7 tcp and man setsockopt.

I used this to speed up the connect-timeout in a program I needed to patch quickly. Hacking it to timeout via select()/poll() was not an option.