Linux网络编程accept的讲解

accept 是服务器端从监听队列里取出一个已经建立好的连接,并为这个客户端创建一条专属通信通道。

cpp 复制代码
int connfd = accept(_sockfd, (struct sockaddr*)&client_addr, &len);

它做了两件事

1. 从队列里取一个连接

之前 listen 已经建好了等待队列,客户端完成三次握手后就在里面排队。accept 就是从队列里取出一个,如果队列为空,accept 会阻塞,一直等到有客户端连进来。

2. 返回一个新的文件描述符

这是最关键的一点。accept 返回的 connfd 和原来的 _sockfd 是两个不同的东西:

表格

描述符 作用 生命周期
_sockfd 监听套接字,只负责接受新连接 服务器启动到关闭,一直存在
connfd 通信套接字,专门和这个客户端收发数据 这个客户端断开后就关闭

为什么需要两个描述符?

想象一个餐厅:

  • _sockfd 是门口的迎宾员,只管接待新客人,把客人领进来;
  • connfd 是专属服务员,只服务这一桌客人,点菜、上菜、结账都靠它。

迎宾员不能同时服务所有桌子,所以需要为每桌客人分配一个专属服务员。

如果服务器只用 _sockfd 和客户端通信,那当它正在和客户端 A 聊天时,客户端 B、C 的新连接就没人处理了。有了 connfd,_sockfd 可以立刻回到 accept 继续接待下一个客人,而 connfd 专门负责和当前客户端通信。

典型服务器循环

cpp 复制代码
while (true) {
    int connfd = accept(_sockfd, ...);  // 等待新客户端,返回专属通道
    // 用 connfd 和这个客户端收发数据
    read(connfd, buf, ...);
    write(connfd, resp, ...);
    close(connfd);  // 这个客户端走了,关闭专属通道
}

_sockfd 始终在循环里反复 accept,每来一个客户端就产生一个新的 connfd。

参数里的 client_addr

cpp 复制代码
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int connfd = accept(_sockfd, (struct sockaddr*)&client_addr, &len);

调用后 client_addr 里就填好了客户端的 IP 和端口,你可以知道是谁连进来了。如果不需要,这两个参数可以传 NULL。

一句话总结

accept 就是:从监听队列里拿出一个已完成握手的连接,返回一个专属的文件描述符用来和这个客户端通信,同时让监听套接字继续接待下一个。

相关推荐
坤坤子吖1 小时前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习
阡陌数智2 小时前
Claude API新版本重大变更与安全升级指南
java·linux·安全
奶茶树2 小时前
【Linux】环境开发工具(vim,gcc,g++,Makefile)
linux·运维·vim
一晌小贪欢2 小时前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
xiaoye-duck3 小时前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
say_fall3 小时前
【AI大模型】MCP 模型上下文协议:客户端-服务器架构、JSON-RPC 消息与能力协商、工具发现与调用链路、与函数调用的分工
服务器·人工智能·架构
一条大祥脚3 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
·present·3 小时前
CSAPP(lecture 13_02 Linking)
c语言·c++
旖旎夜光4 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习
木子欢儿5 小时前
国内 macOS/Linux 安装 rust
linux·运维·服务器·macos·rust