简体   繁体   中英

Timeout on an accept socket function

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:

  • socket()
  • bind()
  • listen()
  • select()
  • accept()

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM