我正在尝试了解BSD套接字接口中的事件如何转换为TCP连接的状态。特别是,我试图了解连接过程accept()
在服务器端返回的哪个阶段
accept()
返回哪个步骤?
答案 0 :(得分:5)
accept
返回。客户端发送ACK 后,连接完成。
accept
为您提供了一个可以与之通信的套接字。当然,您知道,在建立连接之前,您无法进行通信。并且在握手之前无法建立连接。
在客户感知他的ACK之前返回是没有意义的。在最初的SYN之后,他完全有可能不会说什么。
答案 1 :(得分:1)
内核中的TCP / IP堆栈代码通常[1]完全完成三次握手,无需任何用户空间代码的干预。您列出的三个步骤都是在 accept()
返回之前发生。实际上,它们可能会在accept()
被召唤之前发生!
当您告诉堆栈listen()
特定TCP端口上的连接时,您传递一个backlog
参数,该参数告诉内核它可以代表您的程序一次静默接受多少个连接。当内核自动接受新的连接请求时,正在使用此队列,并且在程序到达accept()
之前它们一直处于保持状态。当您调用accept()
时,listen backlog队列中有一个或多个连接,所有发生的事情都是从队列中删除最旧的连接并绑定到新套接字。[2]
换句话说,如果您的程序调用{{1}},然后进入无限无操作循环,以便它永远不会调用listen(sd, 5)
,则从客户端点开始,五个并发客户端连接请求将成功观点。第六个连接请求将在第一个SYN数据包上停止,直到拥有TCP端口的程序调用{{1}}或其中一个客户端断开其连接。
[1]当然,防火墙和其他堆栈修改可以改变这种行为。我这里只讲默认的BSD套接字堆栈行为。
[2]如果在调用accept()
时在backlog中没有等待连接,则默认情况下会阻塞,除非侦听器套接字设置为非阻塞,在这种情况下它返回-1和{{ 1}}是accept()
。