6.7 str_cli Function
(Revisited Again)
Figure
6.13 shows our revised (and correct) version of the
str_cli function. This version uses select and
shutdown. The former notifies us as soon as the server
closes its end of the connection and the latter lets us handle
batch input correctly. This version also does away with
line-centric code and operates instead on buffers, eliminating the
complexity concerns raised in Section 6.5.
Figure 6.13
str_cli function using select that handles EOF
correctly.
select/strcliselect02.c
1 #include "unp.h"
2 void
3 str_cli(FILE *fp, int sockfd)
4 {
5 int maxfdp1, stdineof;
6 fd_set rset;
7 char buf[MAXLINE];
8 int n;
9 stdineof = 0;
10 FD_ZERO(&rset);
11 for ( ; ; ) {
12 if (stdineof == 0)
13 FD_SET(fileno(fp), &rset);
14 FD_SET(sockfd, &rset);
15 maxfdp1 = max(fileno(fp), sockfd) + 1;
16 Select(maxfdp1, &rset, NULL, NULL, NULL);
17 if (FD_ISSET(sockfd, &rset)) { /* socket is readable */
18 if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
19 if (stdineof == 1)
20 return; /* normal termination */
21 else
22 err_quit("str_cli: server terminated prematurely");
23 }
24 Write(fileno(stdout), buf, n);
25 }
26 if (FD_ISSET(fileno(fp), &rset)) { /* input is readable */
27 if ( (n = Read(fileno(fp), buf, MAXLINE)) == 0) {
28 stdineof = 1;
29 Shutdown(sockfd, SHUT_WR); /* send FIN */
30 FD_CLR(fileno(fp), &rset);
31 continue;
32 }
33 Writen(sockfd, buf, n);
34 }
35 }
36 }
5鈥?
stdineof is a new flag that is initialized to 0. As long
as this flag is 0, each time around the main loop, we
select on standard input for readability.
17鈥?5
When we read the EOF on the socket, if we have already encountered
an EOF on standard input, this is normal termination and the
function returns. But if we have not yet encountered an EOF on
standard input, the server process has prematurely terminated. We
now call read and write to operate on buffers
instead of lines and allow select to work for us as
expected.
26鈥?4
When we encounter the EOF on standard input, our new flag,
stdineof, is set and we call shutdown with a
second argument of SHUT_WR to send the FIN. Here also,
we've changed to operating on buffers instead of lines, using
read and writen.
We are not finished with our str_cli
function. We will develop a version using nonblocking I/O in
Section 16.2 and a
version using threads in Section 26.3.
|