When shutting down a TCP connection, something curious occurs. The TCP connection is duplex: data flows in both directions. And it's created in this manner -- it is impossible to create "half" a TCP connection, that would let data flow only from one end to the other. The SYN/ACK handshaking creates both directions at once or fails. Of course, your program might use the TCP connection to stream data in only one direction. But both directions are there...
When closing the connection, something else occurs. A party wishing to close its side of the TCP connection sends a FIN (i.e. a header with this bit set, along with any of the usual ACKs etc.). Like a SYN at the beginning of the connection, the FIN consumes a TCP sequence number, so it can be ACKed. And after the other party ACKs, the connection is half-closed! The party which sent the FIN can no longer send data -- but the other party may continue to send data.
To close the TCP stream fully, both sides must send a FIN for "their" half of the connection.
What possible use is a half-open connection?
In fact, a great deal of use. TCP streams share a great deal of intended functionality with UN*X pipes. In particular, it is often useful to think of sending a FIN in the same way as sending an EOF to the other side. Many processes can only compute their output after they finish reading their input. If you wish to connect such a program to a TCP stream, you'll need to denote the end of input in some manner -- and that manner is TCP's FIN.
For instance, suppose we have a program
md5sum which computes the MD5 checksum of its input.
md5sum reads its entire input, and only then generates output. Suppose further I have a file
xyzzy on machine alice, and the program
md5sum on machine bob. How can I compute the checksum?
does the trick
alice% rsh bob md5sum < xyzzy
md5sum cannot produce any output until it knows its read all its input. Thus, no application data will flow from bob to alice until alice sends FIN. As soon as alice sends FIN,
rsh on bob knows that its standard input has ended, and closes
md5sum's input. Now
md5sum can output its application data, which is transmitted on the half-open side of the TCP stream. Immediately following this data comes bob's FIN, closing the other half of the connection.
Without the TCP's half-close, some out of band data would have had to be used, significantly complicating TCP. A half-closed pipe is useful.