Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Aug 1996 12:06:14 -0600 (MDT)
From:      Nate Williams <nate@mt.sri.com>
To:        hackers@freebsd.org
Cc:        nate@rocky.mt.sri.com
Subject:   Non-blocking I/O on sockets and closed sockets?
Message-ID:  <199608231806.MAA07694@rocky.mt.sri.com>

next in thread | raw e-mail | index | archive | help
I need to setup my sockets as non-blocking to avoid some problems, but
it brings up a problem of determining if the remote end has closed the
connection.  Normally, if you run select() on a FD, and the subsequent
read() call returns 0 you can assume the socket is dead.  However, with
non-blocking I/O a read of 0 does *NOT* mean the socket is dead.

Will read() return a negative error code on a socket if the socket is
closed/dead?  I've looked in Steven's and in the obvious manpages, but
nothing jumps out at me.

Here's the code snippet which should explain what goes on.
(error checking removed)

void do_socket(short inport)
{
  struct sockaddr_in addr;
  int s_sock, d_sock, flag;
  
  /* No data yet */
  d_sock = -1;
  s_sock = socket(AF_INET, SOCK_STREAM, 0);
  port = htons(inport);
  
#ifdef DEBUG
  flag = 1;
  setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof flag);
#endif
  
  addr.sin_family = AF_INET;
  addr.sin_port = htons(inport);
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  bind(s_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
  
  /* Make sure the socket is in non-blocking mode */
  flag = fcntl(s_sock, F_GETFL, 0);
  fcntl(s_sock, F_SETFL, flag|O_NONBLOCK);
  
  /* Will not block */
  listen(s_sock, 1);
  
  /* Wait until we get some input */
  for (;;) {
    fd_set input_fds;
  
    FD_ZERO(&input_fds);
    if ( d_sock == -1 )
      FD_SET(s_sock, &input_fds);
    else
      FD_SET(d_sock, &input_fds);
  
    if ( (i = select(FD_SETSIZE, &input_fds, 0, 0, 0)) < 0 ) {
      if ( errno == EINTR )
        continue;
      perror("Select loop");
      exit(1);
    }
  
    /* Connection request? */
    if ( d_sock == -1 ) {
      int addrlen = sizeof(addr);
      d_sock = accept(s_sock, (struct sockaddr *)&addr, &addrlen);
  
      /* non-blocking mode */
      flag = fcntl(d_sock, F_GETFL, 0);
      fcntl(d_sock, F_SETFL, flag|O_NONBLOCK);
    } else {
      char lbuff[255];
  
      /*
       * We may have more data than can fit in lbuff, so read in lbuff
       * size chunks.
       * XXX - How do we determine if the socket is closed?
       */
      do {
        i = read(data->stream_sock, lbuff, 512);
        if ( i > 0 )
          save_data(lbuff, i);
      } while ( i > 0 );
    }
  }
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199608231806.MAA07694>