shutdown function.
The normal way to terminate a network function is to call the close function. But there are two limitations with close that can be avoided with the shutdown function.
1. Close decrements the descriptors‘ reference
count and closes the socket only if the count reaches 0. With shutdown function, we can initiate
TCP‘s normal connection termination
sequence regardless of the reference count.
2. Close
terminates both directions of data transfer, reading and writing. Since a TCP
connections is full duplex, there are times when we want to tell the other end
that we have finished sending, even though that end might have more data to
send us. This is the scenario we encountered in the previous section with batch
input to our str_cli function. Following figure shows the typical scenario
Syntax of shutdown () function
int
shutdown (int sockfd, int howto); Returns : 0 if OK, -1 on error.
The action of the function depends on the value
of the howto argument.
SHUT_RD – The read half of the connection is
closed. NO more data can be received on the
socket and any data currently in the socket receive buffer is discarded. He
process can no longer issue any of the read functions on the socket. Any data
received after this call for a TCP sockets is acknowledged and then silently
dropped.
SHUT_WR : The
write half of the connection is closed. IN the case of TCP, this is called half close. Any data currently in the
socket
SHUT_RW: Read
half and write half of the connections are both closed.
The following code gives the str_cli function
that is modified by using shutdown function:
# include ―unp.h‖
void str_cli (FILE *fp, int socket)
{
int maxfdp1, stdineof;
fd_set rset;
char sendline[MAXLINE], recvline[MAXLINE];
stdineof = 0;
FD_ZERO (&rset);
for ( ; ;)
{
if (stdineof ==0)
FD_SET (fileno (fp), &rset);
FD_SET (sockfd, &rset);
maxfdp1 = max (fileno (fp), sockfd) + 1;
select (maxfdp1, &rset, NULL, NULL, NULL);
if (FD_ISSET(sockfd, &rset))
{ if
(readline (sockfd, recvline, MAXLINE)==0) { if ( stdineof ==0 )
return;
else
err_quit (―str_cli: server terminated
prematurely‖);
}
fputs (recvline, stdout);
}
if (FD_ISSET(fileno(fp), &rset))
{ if
(fgets (sendline, MAXLINE, fp)==NULL) {stdineof = 1;
shetdown (sockfd, SHUT_WR); FD_CLR (fileno(fp),
&rset); continue;
}
writen(sockfd, sendline, strlen (sendline));
}
}
}
IN this stdineof
in 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.
When we read the end of file on the socket, if
we have already encountered an of file on standard input, this is the normal
termination and the function returns. But if the end of file is not encountered
on the standard input, the server process is prematurely terminated/
When we encounter the end of file on standard
input, the new flag is set to 1 and we call shutdown with a second argument of
SHUT_WR to send the FIN.
TCP Echo Server with IO multiplexing:
The TCP echo server can use the select function
to handle any number clients, instead of forking one child per client. This
needs to create two sets of data structures. These are : read descriptors set
and connected socket descriptors set as shown below:
The
server maintains only read descriptors set, which is shown above. When the
server is started in the foreground, the descriptors 0, 1 and 2 are set to
standard input, output and error. Therefore the available descriptors for the
listening socket is 3.
Another
client descriptors set is also shown. It is shows the number of the connected
socket descriptors for each client. All elements of this array are initialized
to –1.
The only
non zero entry in the descriptors set is the entry of listening socket and the
first argument to select will be 4.
When the first client establishes a connection
with our server, the listening descriptors becomes readable and the server
calls accept. The new connected descriptor returned by accept will be given, as
per the assumption . From now on the server must remember the new connected
socket in its client array and the connected socket must be added to the
descriptor set. The updated data set is shown below.
Some time later a second client establishes a
connection and we have the scenario as shown below:
The new connected socket which we assume as 5,
must be remembered, giving the data structure as shown above.
When the first client terminates its
connection, the client TCP sends FIN, makes descriptors in the server readable.
When our server reads this connected socket, readline returns 0. We then close
this colet and update our data structure accordingly. The value of the
client[0] is set –1. and descriptors 4 in the descriptors is set to 0. The
value of mxfd does not change.
That is as the client arrive we record their
connected socket descriptor in the first available entry in the client array ()
the first entry with a value of –1. We must also add the connected socket to
the descripto set. The variable maxi is the highest index in the current value
of the first argument select. The only limit on the number of descriptors
allowed for this process by the kernel. The first half server side programme is
given below:
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.