In TCP we say one side of the connection performs an "active close" and the other side performs a "passive close".
In terms of the Linux sockets API, how do you differentiate the active close and the passive close?
For example, suppose we have two connected Linux TCP sockets, A and P, that have exchanged information over the application-level protocol and they are both aware that it is time to close their sockets (neither expect to send or receive any more data to or from each other).
We want socket A to perform the active close, and for P to be the passive close.
There are a few things A and P could do. For example:
What combination of these things and in what order should A do?... and what combination of these things and in what order should P do?
Active sockets are connected with the remote active sockets through an open data connection. If this connection is closed, the active sockets at each end point is destroyed. Passive sockets are not connected; instead, they wait for an incoming connection that will spawn a new active socket.
The program that initiates the closedown process by issuing the first close() call is said to initiate an active close. The program that closes in response to the initiation is said to initiate a passive close.
However, there are two different kinds of OPEN: Active OPEN: A client process using TCP takes the “active role” and initiates the connection by actually sending a TCP message to start the connection (a SYN message). Passive OPEN: A server process designed to use TCP, however, takes a more “laid-back” approach.
A passive socket or acceptor socket is a type of socket that is used to wait for connection establishment requests from remote applications that communicate over the TCP protocol.
In terms of the Linux sockets API, how do you differentiate the active close and the passive close?
The 'active' close is simply whichever side of the socket sends a FIN
or RST
packet first, typically by calling close()
.
What combination of these things and in what order should A do?... and what combination of these things and in what order should P do?
In practice, most of this is application- and application-protocol specific. I will describe the minimum/typical requirement to answer your question, but your mileage may vary depending on what you are specifically trying to accomplish.
You may first call shutdown()
on Socket A if you want to terminate communication in one direction or the other (or both) on Socket A. From your description, both programs already know they're done, perhaps due to application protocol messages, so this may not be necessary.
You must call close()
on Socket A in order to close the socket and release the file descriptor.
On Socket P, you simply keep reading until recv()
returns 0
, and then you must call close()
to close the socket and release the file descriptor.
For further reading, there are a number of good tutorials out there, and Beej's Guide to Network Programming is quite popular.
Active open is when you issue connect(2)
explicitly to make a connection to a remote site. The call blocks until you get the socket opened on the other side (except if you issued O_NONBLOCK
fcntl(2)
call before calling connect(2)
.
Passive open is when you have a socket listen(2)
ing on a connection and you have not yet issued an accept(2)
system call. The accept(2)
call normally blocks until you have a completely open connection and gives you a socket descriptor to communicate over it, or gives you inmediately a socket descriptor if the connection handshake has already finished when you issue the accept(2)
syscall (this is a passive open). The limit in the number of passively open connections the kernel can accept on your behalf while you prepare yourself to make the accept(2)
system call is what is called the listen(2)
value.
Active close is what happens when you explicitly call shutdown(2)
or close(2)
system calls. As with passive open, there's nothing you can do to make a passive close (it's something that happens behind the scenes, product of other side's actions). You detect a passive close when the socket generates an end of file condition (this is, read(2)
always returns 0
bytes on reading) meaning the other end has done a shutdown(2)
(or close(2)
) and the connection is half (or full) closed. When you explicitly shutdown(2)
or close(2)
your side, it's an active close.
if the other end does an explicit close(2)
and you continue writing on the socket, you'll get an error due to the impossibility of sending that data (in this case we can talk about a passive close(2)
---one that has occured without any explicit action from our side) but the other end can do a half close calling shutdown(2)
. This makes the tcp to send a FIN
segment only and conserves the socket descriptor to allow the thread to receive any pending data in transit or not yet sent. Only when it receives and acknowledges the other end's FIN
segment will it signal you that no more data remains in transit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With