I'm trying to set a timeout on an accept socket function without success. I would like the accept function blocks until the end of the timeout delay. Is it possible without setting the accept function non-blocking ? I have tried out many possibilities without success.
Thanks for your answers.
Below is my code :
struct timeval tv;
fd_set readfds;
tv.tv_sec = 1;
tv.tv_usec = 0;
int s, s_remote;
struct sockaddr_un remote;
struct sockaddr_un local;
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
FD_ZERO(&readfds);
FD_SET(s, &readfds);
if (select(s+1, &readfds, NULL, NULL, &tv) > 0) {
printf("Waiting for a connection...\n");
memset(&local, 0, sizeof(local));
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
if (bind(s, (struct sockaddr *)&local, sizeof(local)) == -1) {
perror("UnixSocketClient :: error bind.\n");
close(s);
return -1;
}
if (listen(s, 5) == -1) {
perror("UnixSocketClient :: error listen.\n");
close(s);
return -1;
}
socklen_t remote_len = sizeof(remote);
printf("Accept :\n\r");
if ((s_remote = accept(s, (struct sockaddr *)&remote, &remote_len)) == -1) {
perror("UnixSocket :: error accept.\n");
return -1;
}
printf("Client accepted\n\r");
}
Your code makes no sense. You have to call:
in that order.
On the listening socket call select()
with a time-out set and only call accept()
if select()
did not time out.
Update:
The above approach (which in fact is the same as in this answer ) indeed introduces a race , as discussed in the comments to this answer. If select return indicating an incoming connecting, there is a (short) delay until accept is called. If during this delay the connection is gone, then accept()
will block.
The only way to manoeuvre around this is to use a non-blocking socket when calling accept()
.
If the requirement (for what ever reasons) is to use a blocking socket, then a possible solution would be to send a signal to the process blocked in accept()
, which made it return with a value of -1
and having errno
set EINTR
.
void handle_sigalarm(int sig)
{
/* do nothing */
}
...
sigaction(SIGALRM , &(struct sigaction){handle_sigalarm}); /* Setup handler for
alarm signal to override the default behaviour which would be to
end the process . */
alarm(3); /* Arranges for a SIGALRM signal to be delivered to the calling
process in 3 seconds. */
{
int accepted_socket = accept(...);
int errno_save = errno;
alarm(0); /* Cancel any pending alarm. */
if (-1 == accepted_socket)
{
if (EINTR == errno_save)
{
fprintf(stderr, "accept() timed out\n");
}
/* handling other errors here. */
}
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.