In order to establish a connection, the accept function is called (read man 2 accept).
The accept call takes the same parameters as bind. However, accept serves a very different purpose.
accept extracts the first connection request that is queued up to the end-point identified by the first parameter (the FD of the end-point). If no request is queued, then the call is blocked. This means that it will not return until a request arrives at the queue.
A blocking call is not always desirable, especially in a single-threaded program. For single-threaded programs, accept4 can be used instead. The first three parameters of accept4 are the same as an accept call (hence also the same as a bind call). However, accept4 also has a fourth parameter called flags. If SOCK_NONBLOCK is specified as flags, then the call does not block.
accept and accept4 returns a non-negative value that is the FD of the connection (as opposed to the end-point). If -1 is returned instead, it means an error may have occurred.
This is one instance that the global variable errno must be interpreted. Particularly, if ((errno == EWOULDBLOCK) || (errno == EAGAIN)), it means that the non-blocking accept4 call did not find any queued connection requests.
It is important to remember that we have to deal with two different FDs here. The end-point (from socket) FD identifies the the end point, which is kind of like a street address. However, the connection (from accept or accept4) FD identifies an actual connection to an end point, analoguous to a letter sent to a street address.
This implies that a single end-point FD may have any number (0 or more) of connection FDs associated with it.
Once accepted, a process can use read and write to utilize the connection FD.