UNIT III - APPLICATION DEVELOPMENT TCP Echo Server TCP Echo Client Posix Signal handling Server with multiple clients boundary conditions: Server process Crashes, Server host Crashes, Server Crashes and reboots, Server Shutdown I/O multiplexing I/O Models select function shutdown function TCP echo Server (with multiplexing) poll function TCP echo Client (with Multiplexing). TCP Echo Server 1. The Client reads a line of text from its standard input and writes the line to the server. 2. The server reads the line from its network input and echoes the line back to the client. 3. The client reads the echoed line and prints it on its standard output. voidstr_echo(intsockfd) { ssize_t n; 1 CCET
} } char line[maxline]; for ( ; ; ) { if ( (n = Readline(sockfd, line, MAXLINE)) == 0) return; /* connection closed by other end */ Writen(sockfd, line, n); TCP Echo Client } voidstr_cli(file *fp, intsockfd) { char sendline[maxline], recvline[maxline]; while (Fgets(sendline, MAXLINE, fp)!= NULL) { Writen(sockfd, sendline, strlen(sendline)); if (Readline(sockfd, recvline, MAXLINE) == 0) err_quit("str_cli: server terminated prematurely"); Fputs(recvline, stdout); } } Posix Signal Handling Signal (software interrupt): sent by one process to another process (or to itself) or by the kernel to a process 2 CCET
SIGCHLD: by the kernel to the parent Disposition of a signal: catch the signal by a specified signal handler SIG_IGN: ignore it SIG_DFL: default: terminate or ignore To enable automatic restart of an interrupted system call by the kernel -- write our own signal function. Sigfunc *Signal(int signo, Sigfunc *func) /* for our signal() function */ { Sigfunc *sigfunc; if ( (sigfunc = signal(signo, func)) == SIG_ERR) err_sys("signal error"); return(sigfunc); } POSIX signal semantics: 1. Once a signal handler is installed, it remains installed. 2. The signal being delivered is blocked while a signal handler is executing. 3. By default, signals are not queued. Boundary Conditions I) II) Crashing of Server Process Procedure: 1. Server TCP sends FIN to client TCP, which responds with an ACK. (TCP half-close) (The client process is blocked in fgets when client TCP receives FIN.) 2. SIGCHLD signal is sent to the server parent. 3. The client process calls writen to send data to server. 4. The server TCP responds with an RST. 5. The client process returns from readline, 0, when client TCP receives RST. 6. The client process terminates. Problem: The client should be aware of server process crash when FIN is received. Solution: Use select or poll to block on either socket or stdio. (when writing to a socket that has received an RST ) SIGPIPE Signal Procedure: 3 CCET
III) 1. The client writes to a crashed server process. An RST is received at the client TCP and readline returns 0 (EOF). 2. If the client ignores the error returned from readline and write more, SIGPIPE is sent to the client process. 3. If SIGPIPE is not caught, the client terminates with no output. Problem: Nothing is output even by the shell to indicate what has happened. (Have to use echo $? to examine the shell s return value of last command.) Solution: Catch the SIGPIPE signal for further processing. The write operation returns EPIPE. Crash, Reboot, Shutdown of Server Host Crash of server host: client TCP continuously retx data and timeout around 9 min readline returns ETIMEDOUT or EHOSTUNREACH To quickly detect: timeout on readline, SO_KEEPALIVE socket option, heartbeat functions Reboot of server host: After reboot, server TCP responds to client data with an RST readline returns ECONNRESET Shutdown (by operator) of server host: init process sends SIGTERM to all processes init waits 5-20 sec and sends SIGKILL to all processes I/O Multiplexing Scenarios for I/O Multiplexing client is handling multiple descriptors (interactive input and a network socket). Client to handle multiple sockets (rare) TCP server handles both a listening socket and its connected socket. Server handle both TCP and UDP. Server handles multiple services and multiple protocols I/O Models Models Blocking I/O 4 CCET
Nonblocking I/O I/O multiplexing(select and poll) Signal driven I/O (SIGIO) Asynchronous I/O Two distinct phases for an input operation Waiting for the data to be ready (for a socket, wait for the data to arrive on the network, then copy into a buffer within the kernel) Copying the data from the kernel to the process (from kernel buffer into application buffer) 1) Blocking I/O 2) Nonblocking I/O 5 CCET
3) I/O multiplexing(select and poll) 4) Signal driven I/O (SIGIO) 5) Asynchronous I/O 6 CCET
Comparison of the I/O Models Synchronous I/O, Asynchronous I/O Synchronous I/O causes the requesting process to be blocked until that I/O operation (recvfrom) completes. (blocking, nonblocking, I/O multiplexing, signaldriven I/O) Asynchronous I/O does not cause the requesting process to be blocked Select Function Allows the process to instruct the kernel to wait for any one of multiple events to occur and to wake up the process only when one or more of these events occurs or when a specified amount of time has passed. What descriptors we are interested in (readable,writable, or exception condition) and how long to wait? #include <sys/select.h> #include <sys/time.h> 7 CCET
int select (int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *); //Returns: +ve count of ready descriptors, 0 on timeout, -1 on error struct timeval{ long tv_sec; /* seconds */ long tv_usec; /* microseconds */ } Possibilities for select function Wait forever : return only when descriptor (s) is ready (specify timeout argument as NULL) wait up to a fixed amount of time Do not wait at all : return immediately after checking the descriptors. Polling (specify timeout argument as pointing to a timeval structure where the timer value is 0) The wait is normally interrupted if the process catches a signal and returns from the signal handler select might return an error of EINTR Actual return value from function = -1 select function Descriptor Arguments readset descriptors for checking readable writeset descriptors for checking writable exceptset descriptors for checking exception conditions (2 exception conditions) arrival of out of band data for a socket the presence of control status information to be read from the master side of a pseudo terminal (Ignore) If you pass the 3 arguments as NULL, you have a high precision timer than the sleep function. maxfdp1 argument to select function specifies the number of descriptors to be tested. Its value is the maximum descriptor to be tested, plus one. (hence maxfdp1) Descriptors 0, 1, 2, up through and including maxfdp1-1 are tested example: interested in fds 1,2, and 5 maxfdp1 = 6 Your code has to calculate the maxfdp1 value constant FD_SETSIZE defined by including <sys/select.h> is the number of descriptors in the fd_set datatype. (often = 1024) Condition for a socket to be ready for select 8 CCET
str_cli Function revisited Problems with earlier version could be blocked in the call to fgets when something happened on the socket We need to be notified as soon s the server process terminates Alternatively block in a call to select instead, waiting for either standard input or the socket to be readable. Condition handled by select in str_cli Shutdown Function Close one half of the TCP connection send FIN to server, but leave the socket descriptor open for reading Limitations with close function decrements the descriptor s reference count and closes the socket only if the count reaches 0 With shutdown, can initiate TCP normal connection termination regardless of the reference count 9 CCET
terminates both directions (reading and writing) With shutdown, we can tell other end that we are done sending, although that end might have more data to send us #include<sys/socket.h> int shutdown ( int sockfd, int howto ); /* return : 0 if OK, -1 on error */ howto argument SHUT_RD read-half of the connection closed Any data in receive buffer is discarded Any data received after this call is ACKed and then discarded SHUT_WR write-half of the connection closed (half-close) Data in socket send buffer sent, followed by connection termination SHUT_RDWR - both closed Poll Function poll Provides functionality similar to select, but poll provides additional information when dealing with stream devices. #include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int timeout); Description The poll() function provides applications with a mechanism for multiplexing input/output over a set of file descriptors. For each member of the array pointed to by fds, poll() shall 10 CCET
examine the given file descriptor for the event(s) specified in events. The number of pollfd structures in the fds array is specified by nfds. The poll() function shall identify those file descriptors on which an application can read or write data, or on which certain events have occurred. The fds argument specifies the file descriptors to be examined and the events of interest for each file descriptor. It is a pointer to an array with one member for each open file descriptor of interest. The array's members are pollfd structures within which fd specifies an open file descriptor and events and revents are bitmasks constructed by OR'ing a combination of the following event flags: POLLIN Data other than high-priority data may be read without blocking. For STREAMS, this flag is set in revents even if the message is of zero length. This flag shall be equivalent to POLLRDNORM POLLRDBAND. POLLRDNORM Normal data may be read without blocking.for STREAMS, data on priority band 0 may be read without blocking. This flag is set in revents even if the message is of zero length. POLLRDBAND Priority data may be read without blocking.for STREAMS, data on priority bands greater than 0 may be read without blocking. This flag is set in revents even if the message is of zero length. POLLPRI High-priority data may be read without blocking.for STREAMS, this flag is set in revents even if the message is of zero length. POLLOUT Normal data may be written without blocking.for STREAMS, data on priority band 0 may be written without blocking. POLLWRNORM Equivalent to POLLOUT. POLLWRBAND Priority data may be written.for STREAMS, data on priority bands greater than 0 may be written without blocking. If any priority band has been written to on this STREAM, this event only examines bands that have been written to at least once. POLLERR An error has occurred on the device or stream. This flag is only valid in the revents bitmask; it shall be ignored in the events member. 11 CCET
POLLHUP The device has been disconnected. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred. However, this event and POLLIN, POLLRDNORM, POLLRDBAND, or POLLPRI are not mutually-exclusive. This flag is only valid in the revents bitmask; it shall be ignored in the events member. POLLNVAL The specified fd value is invalid. This flag is only valid in the revents member; it shall ignored in the events member. TCP Echo Server with multiplexing TCP echo server using select Rewrite the server as a single process that uses select to handle any number of clients, instead of forking one child per client. Before first client has established a connection TCP and UDP echo server using select Combine concurrent TCP echo server with iterative UDP server into a single server that uses select to multiplex a TCP and UDP socket Source code in udpcliserv/udpservselect01.c Source code for sig_chld function (signal handler) is in udpcliserv/sigchldpidwait.c Handles termination of a child TCP server 12 CCET