当前位置:

首页 > 编程开发 > C++如何在一个线程中处理多个Socket的I/O

C++如何在一个线程中处理多个Socket的I/O

单线程处理多Socket的核心是平衡资源成本与并发能力。线程创建和切换开销大,1000连接约耗8GB内存。I/O多路复用选型:Linux万级连接首选epoll,跨平台优先poll,仅老系统用select。需注意Socket非阻塞设置、边缘触发与数据读完、关闭后从epoll删除等细节。

不能为每个Socket开一个线程,核心动因是避免线程创建/切换开销过大:1000个连接约耗8GB内存(默认栈8MB),上下文切换成瓶颈,且系统常有线程数硬限制;select、poll、epoll应按平台与规模选型:Linux万级连接首选epoll(O(1)增删、O(k)就绪获取),跨平台优先poll,仅兼容老系统用select。

C++如何在一个线程中处理多个Socket的I/O

先抛个总结:在单线程里处理多个 Socket,本质上是在“资源成本”和“并发能力”之间找平衡。很多新手第一反应是“来一个连接就开一个线程”,但真这么干,系统很快就会被拖垮。下面把核心原因和选型逻辑拆开细说。

为什么不能为每个Socket开一个线程

说白了,核心原因就一个:线程这东西,创建和切换的成本太高了。Linux 下线程默认栈大小是 8MB,假设有 1000 个连接,光栈空间就要吃掉 8GB 内存,这还没算线程本身的控制块开销。更要命的是,当线程数超过 CPU 核数几倍时,上下文切换就会变成系统的主瓶颈——CPU 大部分时间都在“换人”,而不是真正干活。此外,很多环境(比如嵌入式设备或者容器)对线程数有硬性限制,直接搞pthread_create 很可能就返回失败。所以,不是“不能”,而是“不该”。

select / poll / epoll 该怎么选

这三个都是 I/O 多路复用的工具,但适用的场景天差地别:

  • select:好处是跨平台,缺点也很明显——fd_set 有上限(通常是 1024),而且每次调用都要重新初始化集合,遍历所有 fd 检查状态,时间复杂度是 O(n),连接一多就吃力。
  • poll:突破了 fd 数量的硬限制,但依然是遍历所有 struct pollfd,O(n) 的复杂度没跑。好处是在 Windows 上支持得比 epoll 好,跨平台场景下是个更稳妥的选择。
  • epoll(Linux):基于红黑树+就绪链表,增删事件是 O(1),获取就绪事件只关心活跃的 socket(即 O(k),k 是活跃数)。连接数一旦上千,epoll 的优势就非常明显。

所以到底选哪个?看你的目标平台和规模。Linux 环境下连接数能过千的,直接上 epoll;需要跨平台又不想太折腾,优先 poll;除非你还在维护那种古董级别的系统,否则就别碰 select 了。

epoll 使用中容易漏掉的三个细节

epoll 的 API 看着就那么几个函数,但实际项目里翻车往往都在这些“不起眼的地方”:

  • 忘了把 Socket 设为非阻塞模式——这是最常见的坑。如果不执行 fcntl(fd, F_SETFL, O_NONBLOCK),那么 read() 或 write() 在缓冲区空或满时会直接阻塞,整个线程就被卡死了,其他所有 socket 都得等着。
  • 用了水平触发(LT)模式却没读完数据——epoll 默认是 LT,意味着只要 socket 可读,它就会一直通知你。如果你每次只读一点,下次循环又触发,很容易陷入 busy-loop。换成边缘触发(ET)能减少重复通知,但必须确保一次把数据读干净。
  • 关闭 socket 后没从 epoll 实例里删除——epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) 这一步很容易忘。等 fd 被复用后,旧的事件可能突然冒出来,指向一块已经被释放的内存,后果就是野指针崩溃。

如何安全地在单线程里读写多个 socket

本质不在于“怎么注册事件”,而在于“怎么处理就绪事件时才不会阻塞或漏掉”:

  • 每次 epoll_wait() 返回后,必须把本轮所有就绪事件全部处理完,不能只处理第一个——因为一次调用可能给你多个就绪的 socket。
  • 对于可读的 socket,用 recv(fd, buf, len, MSG_DONTWAIT) 或者检查 errno == EAGAIN/EWOULDBLOCK 来判断数据是否已经读完。永远不要假设一次 recv 就能收到一个完整的报文。
  • 写操作要维护发送缓冲区:当 send() 返回值小于待发送的字节数时,说明内核缓冲区满了。这时必须把剩下的数据先存起来,然后注册 EPOLLOUT 事件,等 socket 可写时再继续发,否则数据就丢了。

说句实在话,监听多个 socket 本身一点也不难,真正考验人的是每个 socket 的状态机管理——读到半包怎么办、写被中断了怎么恢复、对端突然断连怎么处理、超时重传怎么搞……这些逻辑堆在一起,复杂度比多线程模型高出一大截。单线程处理 I/O 的路子,对设计精度要求非常高。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发
相关文章 更多
多个网络账号向蔚来公开道歉 赔偿款将用于公益事业
多个网络账号向蔚来公开道歉 赔偿款将用于公益事业

多个网络账号因散布蔚来不实信息,被法院判决公开道歉并赔偿经济损失。蔚来承诺将所有赔偿款定向捐赠至教育、养老等公益项目,践行社会责任。

多个PDF文件怎么免费合并?极轻PDF在线合并方法
多个PDF文件怎么免费合并?极轻PDF在线合并方法

多个PDF文件可通过极轻PDF、Sejda或PDF24Tools在线免费合并。上传前需按顺序编号,合并后必须检查总页数、文件顺序及衔接页是否完整,确保无漏页或重复。建议逐页预览,避免内容错乱。它们完全免费,操作简单快捷,无需安装任何软件。

多个PDF怎么合并?PDF文件如何在线合并?
多个PDF怎么合并?PDF文件如何在线合并?

多个PDF文件可通过极轻PDF、Smallpdf、iLovePDF等在线工具合并。上传前需确认文件完好、命名清晰,调整顺序后合并。下载后重点检查总页数、页序和页面清晰度,确保文件完整无错乱。建议合并前检查文件是否加密或损坏,合并后预览每页内容。

PDF合并怎么按顺序排页码?多个PDF合并后如何检查页面?
PDF合并怎么按顺序排页码?多个PDF合并后如何检查页面?

将多个PDF合并前需按顺序重命名文件,上传后核对列表顺序,合并后检查总页数、衔接位置、页面方向及有无重复或颠倒。极轻PDF、iLovePDF、CleverPDF等工具支持拖拽调整顺序,可辅助完成合并和检查。

多个PDF文件怎么合并成一个?PDF文档如何在线合并?
多个PDF文件怎么合并成一个?PDF文档如何在线合并?

本文介绍三种在线合并PDF的方法:极轻PDF、小PDF和爱PDF。支持一次性上传多个文件,可按自定义顺序合并。完成后下载并检查总页数、页序及清晰度,确保内容连续、页码编号正确。操作简便,无需注册,适合批量处理,安全可靠,且免费易用。

哪些软件可以免费合并PDF?多个PDF在线合并怎么操作?
哪些软件可以免费合并PDF?多个PDF在线合并怎么操作?

在线合并PDF只需三步:上传文件、核对顺序、点击下载。整个过程免费,但需注意文件大小和数量限制,建议分批合并并检查页面衔接,确保顺序无误,避免出错。

Mac怎么把多个图片合成一个PDF
Mac怎么把多个图片合成一个PDF

Mac系统自带了一些方便的工具,能在30秒内把多张图片按顺序合成PDF哦!其中,访达右键“快速操作→创建PDF”这个方法是最快的,只需要3秒就能完成;预览拖拽缩略图调序则最灵活,可以随意调整图片顺序;打印窗口导出呢,支持高质量设置,能满足一些对PDF质量有要求的用户。在Mac上,如果您手头有十几张活

多个PDF文件怎么合并成一个?PDF文档在线合并要怎么操作?
多个PDF文件怎么合并成一个?PDF文档在线合并要怎么操作?

像分项报告、证明材料、课件这类文件,如果零散地分布在几个PDF里,其实完全可以按照你设定的顺序合并成一个文件。这样一来,不管是自己查阅、发给别人,还是后续归档保存,都会省事不少。下面整理了3种完整的操作方法,而且每一步都配好了对应的操作图。 方法一:用极轻PDF合并多个PDF极轻PDF(pdf.cn

多个PDF怎么合并成一个?PDF文件在线合并要怎么操作?
多个PDF怎么合并成一个?PDF文件在线合并要怎么操作?

日常处理资料时,常常会遇到这种情况:合同、报告、扫描件分散在不同文件里,最后却需要整理成一份完整的PDF。其实,用在线工具就能按自己的顺序把它们快速合并好。下面就用两种常见方法来说明,分别是极轻PDF(pdf.cn)和 iLovePDF,而且都会从操作开始一直讲到下载完成为止。 方法一:用极轻PDF

长PDF怎么拆分成多个文件?PDF拆分后如何下载?
长PDF怎么拆分成多个文件?PDF拆分后如何下载?

要是遇到那种页数超多的长PDF文件,直接用极轻PDF(pdf.cn)按照选好的页码范围来拆分就可以啦。不过动手之前,得先把自己想要保留的页面捋清楚哦,拆分完了以后,还得挨个检查一下生成的新文件,免得之前页码设置出了错呢。 在线拆分长PDF文档 步骤一:进入拆分PDF工具 首先,打开网站的首页。接着,

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程
PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
Postman macOS版
Postman macOS版
Mac

Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。

Docker Desktop macOS版
Docker Desktop macOS版
Mac

Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。

Android Studio macOS版
Android Studio macOS版
Mac

Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。

WINDOWS 更多
PixPix 网页版
PixPix 网页版
Windows

PixPix 是面向品牌、卖家和内容团队的在线 AI 图片视频创作平台,提供图视频 Agent、无限画布、图片生成、视频生成、自然语言编辑及商品套图、产品精修和带货视频等电商工具。

Postman Windows版
Postman Windows版
Windows

Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等

Docker Desktop Windows版
Docker Desktop Windows版
Windows

Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。