Chapter 13.

    Advanced
          I / O Functions


              UNIX Network Programming
                                     1
13.1 Introduction

•   Socket Timeouts
•   recv and send Functions
•   readv and writev Functions
•   recvmsg and sendmsg Function
•   Ancillary Data
•   How much Data is Queued?
•   Sockets and Standard I/O
•   T/TCP




                      UNIX Network Programming
                                             2
13.2 Socket Timeouts
• Three ways to place a timeout on an I/O operation involving a
  socket

   – Call alarm, which generates the SIGALRM signal when the
     specified time has expired.

   – Block waiting for I/O in select, which has a time limit built in,
     instead of blocking in a call to read or write.

   – Use the newer SO_RCVTIMEO and SO_SNDTIMEO socket
     options.



                       UNIX Network Programming
                                              3
Connect with a Timeout Using SIGALRM (figure 13.1)
 #include         "unp.h"

 static void      connect_alarm(int);

 int connect_timeo(int sockfd, const SA *saptr, socklen_t salen, int nsec)
 {
    Sigfunc   *sigfunc;
    int                n;

     sigfunc = Signal(SIGALRM, connect_alarm);
     if (alarm(nsec) != 0)
       err_msg("connect_timeo: alarm was already set");

     if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0) {
       close(sockfd);
       if (errno == EINTR)
                errno = ETIMEDOUT;
     }
     alarm(0);                                   /* turn off the alarm */
     Signal(SIGALRM, sigfunc); /* restore previous signal handler */

     return(n);
 }

 static void
 connect_alarm(int signo)
 {
    return;           /* just interrupt the connect() */
 }
                            UNIX Network Programming
                                                   4
recvfrom with a Timeout Using SIGALRM (figure 13.2)
#include "unp.h"
static void        sig_alrm(int);
void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
   int n;
   char sendline[MAXLINE], recvline[MAXLINE + 1];
    Signal(SIGALRM, sig_alrm);
    while (Fgets(sendline, MAXLINE, fp) != NULL) {
         Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
         alarm(5);
         if ( (n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) {
                  if (errno == EINTR)
                           fprintf(stderr, "socket timeoutn");
                  else
                           err_sys("recvfrom error");
         } else {
                  alarm(0);
                  recvline[n] = 0; /* null terminate */
                  Fputs(recvline, stdout);
         }
    }
}
static void sig_alrm(int signo)
{
   return;                          /* just interrupt the recvfrom() */
}
                            UNIX Network Programming
                                                   5
recvfrom with a Timeout Using select (figure 13.3)

 #include    "unp.h"

 int
 readable_timeo(int fd, int sec)
 {
   fd_set                  rset;
   struct timeval tv;

     FD_ZERO(&rset);
     FD_SET(fd, &rset);

     tv.tv_sec = sec;
     tv.tv_usec = 0;

     return(select(fd+1, &rset, NULL, NULL, &tv));
      /* 4> 0 if descriptor is readable */
 }


                        UNIX Network Programming
                                               6
recvfrom with a Timeout Using the SO_RCVTIMEO Socket
Option (figure 13.5)
void
dg_cli(FILE *fp, int    sockfd, const SA *pservaddr, socklen_t servlen)
{
   int                   n;
   char                  sendline[MAXLINE], recvline[MAXLINE + 1];
   struct timeval        tv;

    tv.tv_sec = 5;
    tv.tv_usec = 0;
    Setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

    while (Fgets(sendline, MAXLINE, fp) != NULL) {

        Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

        n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
        if (n < 0) {
                 if (errno == EWOULDBLOCK) {
                          fprintf(stderr, "socket timeoutn");
                          continue;
                 } else
                          err_sys("recvfrom error");
        }
        recvline[n] = 0; /* null terminate */
        Fputs(recvline, stdout);
    }
}                         UNIX Network Programming
                                                 7
13.3 recv and send Functions

#include <sys/socket.h>

ssize_t recv (int sockfd, void *buff, size_t nbytes, int flags);

ssize_t send (int sockfd, const void *buff, size_t nbytes, int flags);




          Flags                       Description              recv   send
   MSG_DONTROUTE          bypass routing table lookup                  •
   MSG_DONTWAIT           only this operation is nonblocking    •      •
   MSG_OOB                send or receive out-of-band data      •      •
   MSG_PEEK               peek at incoming message              •
   MSG_WAITALL            wait for all the data                 •
                     Figure 13.6 flags for I/O functions




                          UNIX Network Programming
                                                 8
13.4 readv and writev Functions

#include <sys/uio.h>

ssize_t readv (int filedes, const struct iovec *iov, int iovcnt);

ssize_t writev (int filedes, const struct iovec *iov, int iovcnt);

 Struct iovec {
         void   *iov_base;         /* starting address of buffer */
         size_t iov_len;                 /* size of buffer */
 };


   – readv and writev let us read into or write from one or more
     buffers with a single function call.
      • are called scatter read and gather write.




                          UNIX Network Programming
                                                 9
13.5 recvmsg and sendmsg Functions
#include <sys/socket.h>

ssize_t recvmsg (int sockfd, struct msghdr *msg, int flags);

ssize_t sendmsg (int sockfd, struct msghdr *msg, int flags);



Struct msghdr {
     void         *msg_name; /* starting address of buffer */
     socklen_t    msg_namelen; /* size of protocol address */
     struct iovec         *msg_iov; /* scatter/gather array */
     size_t       msg_iovlen; /* # elements in msg_iov */
     void         *msg_control; /* ancillary data; must be aligned
                                 for a cmsghdr structure */
     socklen_t    msg_controllen; /* length of ancillary data */
     int          msg_flags; /* flags returned by recvmsg() */
};


                      UNIX Network Programming
                                             10
13.5 recvmsg and sendmsg Functions (cont.)

                      Examined by:         Examined by:            Returned by:
                        Send flags           recv flags
     Flag
                       Sendto flags        recvfrom flags
                      Sendmsg flags        recvmsg flags       Recvmsg msg_flags
MSG_DONTROUTE                •
MSG_DONTWAIT                 •                     •
MSG_PEEK                                           •
MSG_WAITALL                                        •
MSG_EOR                      •                                            •
MSG_OOB                      •                     •                      •
MSG_BCAST                                                                 •
MSG_MCAST                                                                 •
MSG_TRUNC                                                                 •
MSG_CTRUNC                                                                •

       Figure 13.7 Summary of input and output flags by various I/O functions



                         UNIX Network Programming
                                                11
13.5 recvmsg and sendmsg Functions (cont.)


        m s g h d r{ }
  m   sg_nam e
  m   s g _ n a m e le n        16                io v e c { }
  m   s g _ io v                            io   v_base
                                                                 100
  m   s g _ io v le n           3           io   v _ le n
  m   s g _ c o n tro l                     io   v_base
                                                                  60
  m   s g _ c o n t r o lle n   20          io   v _ le n
  m   s g _ f la g s            0           io   v_base
                                                                  80
                                            io   v _ le n




         F ig u r e 1 3 . 8 D a t a s t ru c t u r e s w h e n r e c v m s g is c a lle d f o r a U D P s o c k e t .



                                         UNIX Network Programming
                                                                12
13.5 recvmsg and sendmsg Functions (cont.)
                                              s o c k a d d r _ in { }
                                                                         1 6 , A F _ IN E T , 2 0 0 0
                                                                         1 9 8 .6 9 .1 0 .2

       m s g h d r{ }
 m   sg_nam e
 m   s g _ n a m e le n        16              io v e c { } [ ]
 m   s g _ io v                               io v _ b a s e
                                                                         100
 m   s g _ io v le n            3             io v _ le n
 m   s g _ c o n tro l                        io v _ b a s e
                                                                           60
 m   s g _ c o n t r o lle n   20             io v _ le n
 m   s g _ f la g s            0              io v _ b a s e
                                                                           80
                                              io v _ le n

                                               c m s g _ le n            16
                                               c m s g _ le v e l        IP P R O T P _ IP
                                               c m s g _ ty p e          IP _ R E C V D S T A D D R
                                                                         2 0 6 .6 2 .2 2 6 .3 5

                       F ig u re 1 3 . 9 U p d a t e o f F ig u re 1 3 . 8 w h e n re c v m s g re t u rn .


                                            UNIX Network Programming
                                                                   13
13.6 Ancillary Data
• Ancillary data can be sent and received using the msg_control
   and msg_controllen members of the msghdr structure with
   sendmsg and recvmsg functions.


  Protocol    cmsg_level            Cmsg_type                           Description
 IPv4        IPPROTO_IP        IP_RECVDSTADDR          receive destination address with UDP datagram
                               IP_RECVIF               receive interface index with UDP datagram
 IPv6        IPPROTO_IPV6      IPV6_DSTOPTS            specify / receive destination options
                               IPV6_HOPLIMIT           specify / receive hop limit
                               IPV6_HOPOPTS            specify / receive hop-by-hop options
                               IPV6_NEXTHOP            specify next-hop address
                               IPV6_PKTINFO            specify / receive packet information
                               IPV6_RTHDR              specify / receive routing header
 Unix domain SOL_SOCKET        SCM_RIGHTS              send / receive descriptors
                               SCM_CREDS               send / receive user credentials

                          Figure 13.11 summary of uses for ancillary data.




                                 UNIX Network Programming
                                                        14
13.6 Ancillary Data (cont.)
                             m s g _ c o n tro l




                                            cmsg_len
                                            cmsg_level                 c m s g h d r{ }
                                            cmsg_type

                       CMSG_LEN()
                        cmsg_len                pad                                                  a c c i lla r y
                                                                                                   d a ta o b je c t
                                                                                                C M S G _S PA C E ()
                                                   data
      msg_controllen




                                                pad
                                            cmsg_len
                                            cmsg_level                 c m s g h d r{ }
                                            cmsg_type
                       CMSG_LEN()




                                                                                                     a c c i lla r y
                        cmsg_len




                                                pad                                                d a ta o b je c t
                                                                                                C M S G _S PA C E ()

                                                   data



           F ig u r e 1 3 . 1 2 A n c illa r y d a t a c o n t a in in g t w o a n c illa r y d a t a o b je c t s .

                                            UNIX Network Programming
                                                                   15
13.6 Ancillary Data (cont.)


      c m s g h d r{ }                                            c m s g h d r{ }
     cmsg_len                  16                                cmsg_len                  16
     cmsg_level                SO L_S O C KET                    cmsg_level                SO L_SO C KET
     cmsg_type                 S C M _ R IG H T S                cmsg_type                 SC M _C RED S
        d is c rip to r


                                                                    fcred{}




   F ig u r e 1 3 . 1 3 c m s g h d r s t r u c t u r e w h e n u s e d w it h U n ix d o m a in s o c k e t s .




                                     UNIX Network Programming
                                                            16
13.7 How Much Data Is Queued?
• Three techniques - page 365.




                     UNIX Network Programming
                                            17
13.8 Sockets and Standard I/O
• The standard I/O stream can be used with sockets, but there are a
  few items to consider.

   – A standard I/O stream can be created from any desciptor by
     calling the fdopen function. Similarly, given a standard I/O
     stream, we can obtain the corresponding descriptor by calling
     fileno.
   – fseek, fsetpos, rewind functions is that they all call lseek,
     which fails on a socket.
   – The easiest way to handle this read-write problem is to open
     two standard I/O streams for a given socket: one for reading,
     and one for writing.


                      UNIX Network Programming
                                             18
13.8 Sockets and Standard I/O
• Example : str_echo Function using standard I/O
  #include       "unp.h"

  void
  str_echo(int sockfd)
  {
          char             line[MAXLINE];
          FILE             *fpin, *fpout;

         fpin = Fdopen(sockfd, "r");
         fpout = Fdopen(sockfd, "w");

         for ( ; ; ) {
                 if (Fgets(line, MAXLINE, fpin) == NULL)
                    return; /* connection closed by other end */

                 Fputs(line, fpout);
         }
  }

                         UNIX Network Programming
                                                19
13.9 T/TCP: TCP for Transactions

• T/TCP is a slight modification to TCP that can avoid the three-
  way handshake between hosts that have communicated with each
  other recently.




• Benefit
   – all the reliability of TCP is retained
   – maintains TCP’s slow start and congestion avoidance,
     features that are often missing from UDP applications.


                      UNIX Network Programming
                                             20
13.9 T/TCP: TCP for Transactions (cont.)


         c lie n t                                                                s e rv e r
                                                                                           socket, bind,
                                                                                           listen
      socket                                                                               accept(blocks)
      sendto                    SYN, FIN
                                         , d a t a ( re
read(blocks)                                            q ue s t )
                                                                                           a c c e p t re tu rn s
                                                                                           re a d re q u e s t
                                                                                           < s e rv e r p ro c e s s e s re q u e s t>
                                                         ( rep ly)
                                   SYN, F IN, d at a                                       s e n d r e p ly
                                                  en t ' s FIN                             c lo s e
read returns                        ac k o f c li


                                     ac k o f s e
                                                  rver' s FIN


                F ig u r e 1 3 . 1 5 T im e lin e o f m in im a l T / T C P t r a n s a c t io n




                                 UNIX Network Programming
                                                        21

Npc13

  • 1.
    Chapter 13. Advanced I / O Functions UNIX Network Programming 1
  • 2.
    13.1 Introduction • Socket Timeouts • recv and send Functions • readv and writev Functions • recvmsg and sendmsg Function • Ancillary Data • How much Data is Queued? • Sockets and Standard I/O • T/TCP UNIX Network Programming 2
  • 3.
    13.2 Socket Timeouts •Three ways to place a timeout on an I/O operation involving a socket – Call alarm, which generates the SIGALRM signal when the specified time has expired. – Block waiting for I/O in select, which has a time limit built in, instead of blocking in a call to read or write. – Use the newer SO_RCVTIMEO and SO_SNDTIMEO socket options. UNIX Network Programming 3
  • 4.
    Connect with aTimeout Using SIGALRM (figure 13.1) #include "unp.h" static void connect_alarm(int); int connect_timeo(int sockfd, const SA *saptr, socklen_t salen, int nsec) { Sigfunc *sigfunc; int n; sigfunc = Signal(SIGALRM, connect_alarm); if (alarm(nsec) != 0) err_msg("connect_timeo: alarm was already set"); if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0) { close(sockfd); if (errno == EINTR) errno = ETIMEDOUT; } alarm(0); /* turn off the alarm */ Signal(SIGALRM, sigfunc); /* restore previous signal handler */ return(n); } static void connect_alarm(int signo) { return; /* just interrupt the connect() */ } UNIX Network Programming 4
  • 5.
    recvfrom with aTimeout Using SIGALRM (figure 13.2) #include "unp.h" static void sig_alrm(int); void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; Signal(SIGALRM, sig_alrm); while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); alarm(5); if ( (n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) { if (errno == EINTR) fprintf(stderr, "socket timeoutn"); else err_sys("recvfrom error"); } else { alarm(0); recvline[n] = 0; /* null terminate */ Fputs(recvline, stdout); } } } static void sig_alrm(int signo) { return; /* just interrupt the recvfrom() */ } UNIX Network Programming 5
  • 6.
    recvfrom with aTimeout Using select (figure 13.3) #include "unp.h" int readable_timeo(int fd, int sec) { fd_set rset; struct timeval tv; FD_ZERO(&rset); FD_SET(fd, &rset); tv.tv_sec = sec; tv.tv_usec = 0; return(select(fd+1, &rset, NULL, NULL, &tv)); /* 4> 0 if descriptor is readable */ } UNIX Network Programming 6
  • 7.
    recvfrom with aTimeout Using the SO_RCVTIMEO Socket Option (figure 13.5) void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) { int n; char sendline[MAXLINE], recvline[MAXLINE + 1]; struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; Setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL); if (n < 0) { if (errno == EWOULDBLOCK) { fprintf(stderr, "socket timeoutn"); continue; } else err_sys("recvfrom error"); } recvline[n] = 0; /* null terminate */ Fputs(recvline, stdout); } } UNIX Network Programming 7
  • 8.
    13.3 recv andsend Functions #include <sys/socket.h> ssize_t recv (int sockfd, void *buff, size_t nbytes, int flags); ssize_t send (int sockfd, const void *buff, size_t nbytes, int flags); Flags Description recv send MSG_DONTROUTE bypass routing table lookup • MSG_DONTWAIT only this operation is nonblocking • • MSG_OOB send or receive out-of-band data • • MSG_PEEK peek at incoming message • MSG_WAITALL wait for all the data • Figure 13.6 flags for I/O functions UNIX Network Programming 8
  • 9.
    13.4 readv andwritev Functions #include <sys/uio.h> ssize_t readv (int filedes, const struct iovec *iov, int iovcnt); ssize_t writev (int filedes, const struct iovec *iov, int iovcnt); Struct iovec { void *iov_base; /* starting address of buffer */ size_t iov_len; /* size of buffer */ }; – readv and writev let us read into or write from one or more buffers with a single function call. • are called scatter read and gather write. UNIX Network Programming 9
  • 10.
    13.5 recvmsg andsendmsg Functions #include <sys/socket.h> ssize_t recvmsg (int sockfd, struct msghdr *msg, int flags); ssize_t sendmsg (int sockfd, struct msghdr *msg, int flags); Struct msghdr { void *msg_name; /* starting address of buffer */ socklen_t msg_namelen; /* size of protocol address */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data; must be aligned for a cmsghdr structure */ socklen_t msg_controllen; /* length of ancillary data */ int msg_flags; /* flags returned by recvmsg() */ }; UNIX Network Programming 10
  • 11.
    13.5 recvmsg andsendmsg Functions (cont.) Examined by: Examined by: Returned by: Send flags recv flags Flag Sendto flags recvfrom flags Sendmsg flags recvmsg flags Recvmsg msg_flags MSG_DONTROUTE • MSG_DONTWAIT • • MSG_PEEK • MSG_WAITALL • MSG_EOR • • MSG_OOB • • • MSG_BCAST • MSG_MCAST • MSG_TRUNC • MSG_CTRUNC • Figure 13.7 Summary of input and output flags by various I/O functions UNIX Network Programming 11
  • 12.
    13.5 recvmsg andsendmsg Functions (cont.) m s g h d r{ } m sg_nam e m s g _ n a m e le n 16 io v e c { } m s g _ io v io v_base 100 m s g _ io v le n 3 io v _ le n m s g _ c o n tro l io v_base 60 m s g _ c o n t r o lle n 20 io v _ le n m s g _ f la g s 0 io v_base 80 io v _ le n F ig u r e 1 3 . 8 D a t a s t ru c t u r e s w h e n r e c v m s g is c a lle d f o r a U D P s o c k e t . UNIX Network Programming 12
  • 13.
    13.5 recvmsg andsendmsg Functions (cont.) s o c k a d d r _ in { } 1 6 , A F _ IN E T , 2 0 0 0 1 9 8 .6 9 .1 0 .2 m s g h d r{ } m sg_nam e m s g _ n a m e le n 16 io v e c { } [ ] m s g _ io v io v _ b a s e 100 m s g _ io v le n 3 io v _ le n m s g _ c o n tro l io v _ b a s e 60 m s g _ c o n t r o lle n 20 io v _ le n m s g _ f la g s 0 io v _ b a s e 80 io v _ le n c m s g _ le n 16 c m s g _ le v e l IP P R O T P _ IP c m s g _ ty p e IP _ R E C V D S T A D D R 2 0 6 .6 2 .2 2 6 .3 5 F ig u re 1 3 . 9 U p d a t e o f F ig u re 1 3 . 8 w h e n re c v m s g re t u rn . UNIX Network Programming 13
  • 14.
    13.6 Ancillary Data •Ancillary data can be sent and received using the msg_control and msg_controllen members of the msghdr structure with sendmsg and recvmsg functions. Protocol cmsg_level Cmsg_type Description IPv4 IPPROTO_IP IP_RECVDSTADDR receive destination address with UDP datagram IP_RECVIF receive interface index with UDP datagram IPv6 IPPROTO_IPV6 IPV6_DSTOPTS specify / receive destination options IPV6_HOPLIMIT specify / receive hop limit IPV6_HOPOPTS specify / receive hop-by-hop options IPV6_NEXTHOP specify next-hop address IPV6_PKTINFO specify / receive packet information IPV6_RTHDR specify / receive routing header Unix domain SOL_SOCKET SCM_RIGHTS send / receive descriptors SCM_CREDS send / receive user credentials Figure 13.11 summary of uses for ancillary data. UNIX Network Programming 14
  • 15.
    13.6 Ancillary Data(cont.) m s g _ c o n tro l cmsg_len cmsg_level c m s g h d r{ } cmsg_type CMSG_LEN() cmsg_len pad a c c i lla r y d a ta o b je c t C M S G _S PA C E () data msg_controllen pad cmsg_len cmsg_level c m s g h d r{ } cmsg_type CMSG_LEN() a c c i lla r y cmsg_len pad d a ta o b je c t C M S G _S PA C E () data F ig u r e 1 3 . 1 2 A n c illa r y d a t a c o n t a in in g t w o a n c illa r y d a t a o b je c t s . UNIX Network Programming 15
  • 16.
    13.6 Ancillary Data(cont.) c m s g h d r{ } c m s g h d r{ } cmsg_len 16 cmsg_len 16 cmsg_level SO L_S O C KET cmsg_level SO L_SO C KET cmsg_type S C M _ R IG H T S cmsg_type SC M _C RED S d is c rip to r fcred{} F ig u r e 1 3 . 1 3 c m s g h d r s t r u c t u r e w h e n u s e d w it h U n ix d o m a in s o c k e t s . UNIX Network Programming 16
  • 17.
    13.7 How MuchData Is Queued? • Three techniques - page 365. UNIX Network Programming 17
  • 18.
    13.8 Sockets andStandard I/O • The standard I/O stream can be used with sockets, but there are a few items to consider. – A standard I/O stream can be created from any desciptor by calling the fdopen function. Similarly, given a standard I/O stream, we can obtain the corresponding descriptor by calling fileno. – fseek, fsetpos, rewind functions is that they all call lseek, which fails on a socket. – The easiest way to handle this read-write problem is to open two standard I/O streams for a given socket: one for reading, and one for writing. UNIX Network Programming 18
  • 19.
    13.8 Sockets andStandard I/O • Example : str_echo Function using standard I/O #include "unp.h" void str_echo(int sockfd) { char line[MAXLINE]; FILE *fpin, *fpout; fpin = Fdopen(sockfd, "r"); fpout = Fdopen(sockfd, "w"); for ( ; ; ) { if (Fgets(line, MAXLINE, fpin) == NULL) return; /* connection closed by other end */ Fputs(line, fpout); } } UNIX Network Programming 19
  • 20.
    13.9 T/TCP: TCPfor Transactions • T/TCP is a slight modification to TCP that can avoid the three- way handshake between hosts that have communicated with each other recently. • Benefit – all the reliability of TCP is retained – maintains TCP’s slow start and congestion avoidance, features that are often missing from UDP applications. UNIX Network Programming 20
  • 21.
    13.9 T/TCP: TCPfor Transactions (cont.) c lie n t s e rv e r socket, bind, listen socket accept(blocks) sendto SYN, FIN , d a t a ( re read(blocks) q ue s t ) a c c e p t re tu rn s re a d re q u e s t < s e rv e r p ro c e s s e s re q u e s t> ( rep ly) SYN, F IN, d at a s e n d r e p ly en t ' s FIN c lo s e read returns ac k o f c li ac k o f s e rver' s FIN F ig u r e 1 3 . 1 5 T im e lin e o f m in im a l T / T C P t r a n s a c t io n UNIX Network Programming 21