了解BSD接口

时间:2011-06-28 21:18:51

标签: linux networking tcp

我正在尝试了解BSD套接字接口中的事件如何转换为TCP连接的状态。特别是,我试图了解连接过程accept()在服务器端返回的哪个阶段

  1. 客户端发送SYN
  2. 服务器发送SYN + ACK
  3. 客户端发送ACK
  4. accept()返回哪个步骤?

2 个答案:

答案 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()