I have a simple program to check if a port is open, but I want to shorten the timeout length on the socket connection because the default is far too long. I'm not sure how to do this though. Here's the code:
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
u_short port; /* user specified port number */
char addr[1023]; /* will be a copy of the address entered by u */
struct sockaddr_in address; /* the libc network address data structure */
short int sock = -1; /* file descriptor for the network socket */
if (argc != 3) {
fprintf(stderr, "Usage %s <port_num> <address>", argv[0]);
return EXIT_FAILURE;
}
address.sin_addr.s_addr = inet_addr(argv[2]); /* assign the address */
address.sin_port = htons(atoi(argv[2])); /* translate int2port num */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (connect(sock,(struct sockaddr *)&address,sizeof(address)) == 0) {
printf("%i is open\n", port);
}
close(sock);
return 0;
}
socket timeout — a maximum time of inactivity between two data packets when exchanging data with a server.
Java socket timeout Answer: Just set the SO_TIMEOUT on your Java Socket, as shown in the following sample code: String serverName = "localhost"; int port = 8080; // set the socket SO timeout to 10 seconds Socket socket = openSocket(serverName, port); socket.
Socket timeouts can occur when attempting to connect to a remote server, or during communication, especially long-lived ones. They can be caused by any connectivity problem on the network, such as: A network partition preventing the two machines from communicating. The remote machine crashing.
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 ~7s
setsockopt(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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With