linux网络调用listen函数的backlog详细解释

/ 默认分类 / 0 条评论 / 13浏览

程序逻辑详细描述

在 Linux 中,listen() 函数用于将一个 TCP socket 转换为监听状态,准备接收来自客户端的连接请求。

int listen(int sockfd, int backlog);

当创建一个 socket 时:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

此时它只是一个普通的 TCP socket,状态为 TCP_CLOSE。它不能用来接收连接,因为它还没有告诉内核你想接收谁的连接,监听哪个地址、哪个端口。

然后当执行:

bind(sockfd, ...);   // 绑定IP地址和端口

这个操作只是“注册”了地址和端口,但仍然不能接收连接,此时状态仍然是 TCP_CLOSE。

接下来,调用 listen():

listen(sockfd, backlog);

此时内核执行的关键步骤就是:

把这个 socket 的状态从 TCP_CLOSE 变为 TCP_LISTEN,并初始化连接队列,用于接收客户端的连接请求。

这就是关键的状态改变,意味着从“普通 socket”变成了一个“监听 socket”

现在来总结下完整的过程和一些常见问题:

先通过 socket() + bind() + listen() 创建了一个监听 socket,内核将其置为TCP_LISTEN 状态。客户端通过connect()发起三次握手请求。监听 socket 会响应客户端 SYN,并完成三次握手。握手完成后,内核把这个“已建立连接”放入监听 socket 的“完成连接队列(accept queue)”中。后续的服务端程序通过accept()把这个连接“取出来”,并返回一个新的 socket 文件描述符,用于和该客户端通信。

如果 accept queue 满了,会发生什么?

如果 accept 的速度跟不上,新连接就不能放入完成连接队列,导致无法建立新的连接。

内核处理逻辑如下:

总结