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

相关推荐
Python自动化直播1 小时前
自动化笔记:素材管理、命名、轮换的几条土办法
linux·运维·数据库
开开心心就好2 小时前
白天晚上自动调蓝光,护眼工具亮度可调
服务器·开发语言·算法·pdf·ocr·intellij-idea·idea
西安同步电子2 小时前
卫星信号丢失怎么办?NTP 网络校时服务器的守时能力
运维·服务器·网络
FlightYe2 小时前
音视频修炼之容器与协议(一):MP4和MOV的box剖析
android·linux·c++·ffmpeg·音视频
川石课堂软件测试2 小时前
涨薪技术|0到1学会性能测试第8课-Analysis分析图
服务器·数据库·python·sql·jmeter·mysql·容器
暴雨课堂2 小时前
tp5 tp6被攻击篡改后恢复
linux·服务器·php
学编程的小程2 小时前
服务器日志太分散不好查?我用Promtail+Loki+Grafana把采集、查询和分析串起来了
服务器·python·grafana
音草2 小时前
AVL 树详解:从概念到 C++ 实现
c++
djjjx.2 小时前
Linux进程篇(四):内核托底与生死交错 ,深度硬核剖析“僵尸”与“孤儿”进程
linux·运维·服务器