=========================== EOF handling between client and server =========================== -Ian! D. Allen - idallen@idallen.ca Make sure your client and server handle EOF correctly. A typical client has two processes (or perhaps two threads) - one looping reading Standard Input (often the keyboard) and writing the connected server socket, the other looping reading the connected server socket and writing to Standard Output (usually the screen). Let's call the first one (reading the keyboard) the client Stdin process and the second one (writing the screen) the client Stdout process. On getting EOF (or error) from the keyboard (usually triggerd by ^D), the client Stdin process, before it exits, needs to tell the server that there is nothing more coming down the socket. The client has to signal "EOF" to the server. To do this, the client must use shutdown(fd,SHUT_WR) on the connected server socket before it exits. This shutdown() will close only the writing (not reading) half of the socket. (Don't close the reading half yet! Close only the client writing direction of the socket; make sure the argument to shutdown is 1 or SHUT_WR.) The client Stdout process will continue to run, still reading from non-closed reading half of the server socket. (Only the writing direction of the socket should be shut down using shutdown(fd,SHUT_WR).) After the client Stdin process does shutdown(fd,SHUT_WR), the server will see the EOF on its matching reading half of the client socket, and the server will fully close() the socket at its end. Before the server closes the socket, it might wish to write a "goodbye" message to the client. After the server fully closes its end of the socket, the client Stdout process will now see EOF on the reading half of the server socket. The client Stdout process can then exit. Both client processes have now exited. The sequence is: 1. client Stdin process sees EOF or error on standard input and calls shutdown(fd,SHUT_WR) on the server socket to send "EOF" to the server 2. client Stdin process exits, since there is no more data to write 3. server child sees EOF from client and calls close() on client socket 4. server child exits, since EOF means the client has no more data 5. client Stdout process now sees EOF when reading the server socket 6. client Stdout exits, since there is nothing more to read from the server WARNING for coding servers: In a server that forks to handle clients, some things can prevent EOF from being seen by a client even though a server process calls close() on a client socket. When the server forks after an accept(), both processes (parent and child) have a copy of the open client socket file descriptor. For EOF to be seen by the client on the socket, *both* processes have to close the client socket descriptor. The child process forked to handle the client will usually be the one reading/writing the socket; so, the parent *must* close its duplicate copy of the client socket descriptor. If the parent keeps an open copy of the file descriptor, then even if the child closes its copy of the descriptor the remote client won't see an EOF because the parent still has the descriptor open. In a server that forks children to handle client connections, make sure the parent closes its duplicate copy of the client socket descriptor after the fork(). The forked child process of the server then can call close() and the client will correctly see EOF.