Understanding BSD interface
I'm trying to understand how the events in a BSD socket interface translate to the state of a TCP Connection. In particular, I'm trying to understand at what stage in the connection process accept()
returns on the server side
- client sends SYN
- server sends SYN+ACK
- client sends ACK
In which one of 开发者_开发问答these steps does accept()
return?
accept
returns when the connection is complete. The connection is complete after the client sends his ACK.
accept
gives you a socket on which you can communicate. Of course you know, you can't communicate until the connection is established. And the connection can't be established before the handshake.
It wouldn't make sense to return before the client sens his ACK. It is entirely possible he won't say anything after the initial SYN.
The TCP/IP stack code in the kernel normally[1] completes the three-way handshake entirely without intervention from any user space code. The three steps you list all happen before accept()
returns. Indeed, they may happen before accept()
is even called!
When you tell the stack to listen()
for connections on a particular TCP port, you pass a backlog
parameter, which tells the kernel how many connections it can silently accept on behalf of your program at once. It is this queue that is being used when the kernel automatically accepts new connection requests, and there that they are held until your program gets around to accept()
ing them. When there is one or more connections in the listen backlog queue when you call accept()
, all that happens is that the oldest is removed from the queue and bound to a new socket.[2]
In other words, if your program calls listen(sd, 5)
, then goes into an infinite do-nothing loop so that it never calls accept()
, five concurrent client connection requests will succeed, from the clients' point of view. A sixth connection request will get stalled on the first SYN packet until either the program owning the TCP port calls accept()
or one of the other clients drops its connection.
[1] Firewall and other stack modifications can change this behavior, of course. I am speaking here only of default BSD sockets stack behavior.
[2] If there are no connections waiting in the backlog when you call accept()
, it blocks by default, unless the listener socket was set to non-blocking, in which case it returns -1 and errno
is EWOULDBLOCK
.
精彩评论