Reputation: 56557
I'm testing some code in C and I've found strange behaviour with TCP socket calls.
I've defined one listening thread which accepts clients synchronously and after accepting the client it process it in a for loop until it disconnects. Thus only one client at a time is handled. So I call accept
in a loop and then recv
in an inner loop until received an empty buffer.
I fire 5 threads with clients, I call connect
, send
and finally close
I get no error in any call. Everything seems to be fine.
However when I print received message on the server side it turns out that only the first client got through to the server, i.e. accept
never fires on other clients.
So my questions are:
connect
wait until server calls accept
? Or is the kernel layer taking care of buffering under the hood?Upvotes: 1
Views: 1738
Reputation: 4523
The TCP state-machine performss a synchronized dance with the client's state machine. All of this is performed at OS-level (The TCP/IP stack); the userspace process only can do some systemcalls to influence this machinery now and then. Once the client calls listen()
this machinery is started; and new connections will be establisched.
Remember the second argument for listen(int fd, int backlog)
? The whole 3way handshake is completed (by the TCP stack) before accept()
delivers the fd to the server in userland. So: the sockets are in connected state, but the user process hasn't picked them up yet (by calling accept()
)
Not calling accept()
will cause the new connections to be queued up by the kernel. These connections are fully functional, but obviously the data buffers could fill up and the connection would get throttled.
Suggested reading: Comer& Stevens: Internetworking with TCP/IP 10.6-10.7 (containing the TCP state diagram)
Upvotes: 4