exercises/ex04/trout/trout.c
int recv_dgram ()
{
  int err;
  socklen_t len;
  ssize_t n;
  struct ip *ip;
  int maxfdp1 = max (recvfd, pipefd[0]) + 1;
  fd_set rset[1];
  FD_ZERO (rset);

  alarm(3);       /* set the timeout alarm to handle dropped packets */

  while (1) {
    FD_SET (recvfd, rset);
    FD_SET (pipefd[0], rset);

    n = select (maxfdp1, rset, NULL, NULL, NULL);
    if (n < 0 && errno != EINTR) {
      err_sys ("select error");
    }

    if (FD_ISSET (recvfd, rset)) {
      len = salen;
      n = recvfrom (recvfd, recvbuf, sizeof(recvbuf), 0, sarecv, &len);
      err = errno;
      Gettimeofday (recvtv, NULL);   /* get time of packet arrival */
      if (n < 0 && err != EAGAIN) {
	err_sys ("recvfrom error");
      }
    }

    if (FD_ISSET (pipefd[0], rset)) {
      Read (pipefd[0], &n, 1);
      return -3;                 /* timeout */
    }

    ip = (struct ip *) recvbuf;
    return process_ip (ip, n);
  }
}
/* as Stevens points out in Section 18.5 of Unix Network Programming,
     many programs with alarms have a race condition, which is that
     the alarm might go off before we get to the recvfrom, in which
     case it does nothing and the recvfrom might wait indefinitely.

     In earlier versions of this code, this problem seemed to pop
     up occasionally (although I am not positive about that).

     The use of select here solves that problem.  When the alarm
     goes off, the alarm handler sends a message through the pipe,
     which is one of the things select waits for.

     When select returns, we know that we have received a datagram
     OR the alarm has gone off OR both.  We then use rset to find
     out which, and deal with it.

     According to the specification of select, it should not be possible
     to get to the recvfrom unless there is a datagram waiting, and
     therefore the recvfrom should never block.  Nevertheless, it sometimes
     does, which is why, when we opened it, we set the NONBLOCK flag
     and why, if it fails (errno = EAGAIN) we just go on. */
as Stevens points out in Section 18.5 of Unix Network Programming,
many programs with alarms have a race condition, which is that
the alarm might go off before we get to the recvfrom, in which
case it does nothing and the recvfrom might wait indefinitely.

In earlier versions of this code, this problem seemed to pop
up occasionally (although I am not positive about that).

The use of select here solves that problem.  When the alarm
goes off, the alarm handler sends a message through the pipe,
which is one of the things select waits for.

When select returns, we know that we have received a datagram
OR the alarm has gone off OR both.  We then use rset to find
out which, and deal with it.

According to the specification of select, it should not be possible
to get to the recvfrom unless there is a datagram waiting, and
therefore the recvfrom should never block.  Nevertheless, it sometimes
does, which is why, when we opened it, we set the NONBLOCK flag
and why, if it fails (errno = EAGAIN) we just go on.
as Stevens points out in Section 18 . 5 of Unix Network Programming many programs with alarms have a race condition which is that the alarm might go off before we get to the recvfrom in which case it does nothing and the recvfrom might wait indefinitely . In earlier versions of this code this problem seemed to pop up occasionally ( although I am not positive about that ) . The use of select here solves that problem . When the alarm goes off the alarm handler sends a message through the pipe which is one of the things select waits for . When select returns we know that we have received a datagram OR the alarm has gone off OR both . We then use rset to find out which and deal with it . According to the specification of select it should not be possible to get to the recvfrom unless there is a datagram waiting and therefore the recvfrom should never block . Nevertheless it sometimes does which is why when we opened it we set the NONBLOCK flag and why if it fails ( errno = EAGAIN ) we just go on .
int recv_dgram ()
{
  int err;
  socklen_t len;
  ssize_t n;
  struct ip *ip;
  int maxfdp1 = max (recvfd, pipefd[0]) + 1;
  fd_set rset[1];
  FD_ZERO (rset);
  alarm(3);       
  while (1) {
    FD_SET (recvfd, rset);
    FD_SET (pipefd[0], rset);
    n = select (maxfdp1, rset, NULL, NULL, NULL);
    if (n < 0 && errno != EINTR) {
      err_sys ("select error");
    }
    if (FD_ISSET (recvfd, rset)) {
      len = salen;
      n = recvfrom (recvfd, recvbuf, sizeof(recvbuf), 0, sarecv, &len);
      err = errno;
      Gettimeofday (recvtv, NULL);   
      if (n < 0 && err != EAGAIN) {
	err_sys ("recvfrom error");
      }
    }
    if (FD_ISSET (pipefd[0], rset)) {
      Read (pipefd[0], &n, 1);
      return -3;                 
    }
    ip = (struct ip *) recvbuf;
    return process_ip (ip, n);
  }
}
int recv_dgram ( ) { int err ; socklen_t len ; ssize_t n ; struct ip * ip ; int maxfdp1 = max ( recvfd , pipefd [ 0 ] ) + 1 ; fd_set rset [ 1 ] ; FD_ZERO ( rset ) ; alarm ( 3 ) ; while ( 1 ) { FD_SET ( recvfd , rset ) ; FD_SET ( pipefd [ 0 ] , rset ) ; n = select ( maxfdp1 , rset , NULL , NULL , NULL ) ; if ( n < 0 && errno != EINTR ) { err_sys ( " " ) ; } if ( FD_ISSET ( recvfd , rset ) ) { len = salen ; n = recvfrom ( recvfd , recvbuf , sizeof ( recvbuf ) , 0 , sarecv , & len ) ; err = errno ; Gettimeofday ( recvtv , NULL ) ; if ( n < 0 && err != EAGAIN ) { err_sys ( " " ) ; } } if ( FD_ISSET ( pipefd [ 0 ] , rset ) ) { Read ( pipefd [ 0 ] , & n , 1 ) ; return -3 ; } ip = ( struct ip * ) recvbuf ; return process_ip ( ip , n ) ; } }
as Stevens points out in Section 18.5 of Unix Network Programming,
many programs with alarms have a race condition, which is that
the alarm might go off before we get to the recvfrom, in which
case it does nothing and the recvfrom might wait indefinitely.
as Stevens points out in Section 18 . 5 of Unix Network Programming many programs with alarms have a race condition which is that the alarm might go off before we get to the recvfrom in which case it does nothing and the recvfrom might wait indefinitely .
/* set the timeout alarm to handle dropped packets */ /* get time of packet arrival */ /* timeout */