|
#1
|
|||
|
|||
|
2.6 - When should I use shutdown()?
From Michael Hunter (mphunter@qnx.com): shutdown() is useful for deliniating when you are done providing a request to a server using TCP. A typical use is to send a request to a server followed by a shutdown(). The server will read your request followed by an EOF (read of 0 on most unix implementations). This tells the server that it has your full request. You then go read blocked on the socket. The server will process your request and send the necessary data back to you followed by a close. When you have finished reading all of the response to your request you will read an EOF thus signifying that you have the whole response. It should be noted the TTCP (TCP for Transactions -- see R. Steven's home page) provides for a better method of tcp transaction management. S.Degtyarev (deg@sunsr.inp.nsk.su) wrote a nice in-depth message to me about this. He shows a practical example of using shutdown() to aid in synchronization of client processes when one is the "reader" process, and the other is the "writer" process. A portion of his message follows: Sockets are very similar to pipes in the way they are used for data transfer and client/server transactions, but not like pipes they are bidirectional. Programs that use sockets often fork() and each process inherits the socket descriptor. In pipe based programs it is strictly recommended to close all the pipe ends that are not used to convert the pipe line to one-directional data stream to avoid data losses and deadlocks. With the socket there is no way to allow one process only to send data and the other only to receive so you should always keep in mind the consequences. Generally the difference between close() and shutdown() is: close() closes the socket id for the process but the connection is still opened if another process shares this socket id. The connection stays opened both for read and write, and sometimes this is very important. shutdown() breaks the connection for all processes sharing the socket id. Those who try to read will detect EOF, and those who try to write will reseive SIGPIPE, possibly delayed while the kernel socket buffer will be filled. Additionally, shutdown() has a second argument which denotes how to close the connection: 0 means to disable further reading, 1 to disable writing and 2 disables both. The quick example below is a fragment of a very simple client process. After establishing the connection with the server it forks. Then child sends the keyboard input to the server until EOF is received and the parent receives answers from the server. Code:
/*
* Sample client fragment,
* variables declarations and error handling are omitted
*/
s=connect(...);
if( fork() ){ /* The child, it copies its stdin to
the socket */
while( gets(buffer) >0)
write(s,buf,strlen(buffer));
close(s);
exit(0);
}
else { /* The parent, it receives answers */
while( (l=read(s,buffer,sizeof(buffer)){
do_something(l,buffer);
/* Connection break from the server is assumed */
/* ATTENTION: deadlock here */
wait(0); /* Wait for the child to exit */
exit(0);
}
You should change the client fragment as follows: Code:
if( fork() ) { /* The child */
while( gets(buffer) }
write(s,buffer,strlen(buffer));
shutdown(s,1); /* Break the connection
for writing, The server will detect EOF now. Note: reading from
the socket is still allowed. The server may send some more data
after receiving EOF, why not? */
exit(0);
}
From: brent verner I believe the code examples are incorrectly using the return value of the fork()s excerpt from `man 2 fork` Quote:
For folks new to shutdown(), it's helpful to remind them that shutdown() is NOT a replacement for close(). You still must close() sockets when you're done with them (after the calls to shutdown()) in order to not leak a file descriptor. Many examples of shutdown() omit the close() after shutdown() because they're test programs where the process exits after the shutdown() (and the process exit of course cleans up all open descriptors). Stevens section on shutdown() doesn't make this clear (his wording implies to me an "either/or" between shutdown() and close()). From: george elgin the use of shutdown(1) circumvents what the kernel SHOULD accomplishes automatically. when the open file descriptor count reaches 0 a FIN is sent to the partner which begins the sequence of wait states FIN_WAIT, FIN_WAIT_2 etc. for the reader. When both sides readers have then completed this orderly shutdown the file descriptor is returned to the operating system. i have noticed on some (mostly non-unix) operating systems though a close by all processes (threads) is not enough to correctly flush data, (or threads) is not. A shutdown must be done, but on many systems it is superfulous. From: Newbie >I believe the code examples are incorrectly using the >return value of the fork()s Agree. |
![]() |
| Thread Tools | |
| Display Modes | |
|
|