The accept()
blocks, until another connection is made and the return the sockfd the can communicate both sides on. But why is it accept()
that blocks, when the first thing that is done is the three way handshake. And the handshake is not done by accept()
, but by listen()
. So I would expect to listen()
block rather then accept()
, since it is firstly involved in TCP. I know the kernel does some queuing of the incoming connections, but still the very first function involved in is listen()
, then the connection is moved forward in the queue to accept()
. So when I do first connection, listen()
will do the 3whs, and the server blocks in accept()
. So another connection cannot do another 3whs, becuase the server does no go back to listen()
, which does the 3whs? Or why does accept()
blocks and not listen()
?
listen()
and accept()
are two completely different operations. Yourr understanding of how they work is incorrect.
listen()
merely sets up the listening socket's backlog and opens the bound port, so clients can start connecting to the socket. That opening is a very quick operation, there is no need to worry about it blocking.
A 3-way handshake is not performed by listen()
. It is performed by the kernel when a client tries to connect to the opened port and gets placed into the listening socket's backlog. Each new client connection performs its own 3-way handshake.
Once a client connection is fully handshaked, that connection is made available for accept()
to extract it from the backlog. accept()
blocks (or, if you use a non-blocking listening socket, accept()
succeeds) only when a new client connection is available for subsequent communication.
You call listen()
only 1 time, to open the listening port, that is all it does. Then you have to call accept()
for each client that you want to communicate with. That is why accept()
blocks and listen()
does not.
The listen()
syscall is called only once by the program (server process), and the "listening" is done by the kernel. If a SYN packet is received, the kernel will put it into a queue of "incomplete connections" and will send a SYNACK packet to the client. After the client ACKs the SYNACK (i.e., after the three-way handshake is completed for that connection), the connection in the queue of incomplete connections will be put into a queue of "complete connections". All this is done by the kernel, meaning that it's not "blocking" the execution of the program.
On the other hand, the accept()
syscall is called by the program to return a completed connection from the front of the queue of completed connections. If this queue is empty, the process is put to sleep and waits until a connection arrives at the queue. In this sense, accept()
is blocking the execution of the program (assuming that the socket was set as "blocking").
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