阻塞和非阻塞
“阻塞”和“非阻塞”主要是在说当一个操作暂时无法完成时调用者是停在那里等还是立刻返回。它经常出现在read() write() recv() send() accept() connect()尤其是网络编程里。一、阻塞是什么意思阻塞就是函数暂时做不了就一直等直到能做为止。比如char buf[1024]; recv(sockfd, buf, sizeof(buf), 0);如果sockfd是阻塞 socket并且现在没有数据可读那么recv会卡住。程序会停在这里recv(sockfd, buf, sizeof(buf), 0); // 没数据就不往下走直到发生下面某种情况对端发来了数据对端关闭连接出错被信号打断设置了超时并超时所以阻塞 I/O 的感觉是你要读数据 现在没数据。 那你在这里等着。二、 非阻塞是什么意思非阻塞就是函数暂时做不了也不会等而是马上返回。同样是recv(sockfd, buf, sizeof(buf), 0);如果sockfd是非阻塞 socket并且现在没有数据可读那么recv不会卡住而是返回-1并设置errno EAGAIN || errno EWOULDBLOCK意思是现在没数据你之后再试。所以非阻塞 I/O 的感觉是你要读数据 现在没数据。 我不等直接告诉你暂时不能读。三、 一个直观比喻阻塞你去奶茶店买奶茶。 店员说还没做好。 你站在柜台前一直等什么都不干。 等做好后拿到奶茶再走。非阻塞你去奶茶店问好了没。 店员说还没好。 你马上离开去做别的事。 过一会儿再来问。在程序里“站在那里等”就是线程被阻塞。四、阻塞 read/recv 示例char buf[1024]; ssize_t n recv(fd, buf, sizeof(buf), 0); std::cout recv returned\n;如果fd是阻塞的并且没有数据那么std::cout recv returned\n;这一行不会执行直到recv返回。也就是说整个线程卡在recv上。五、 非阻塞 recv 示例先把 socket 设置成非阻塞#include fcntl.h #include unistd.h void set_nonblocking(int fd) { int flags fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); }然后char buf[1024]; ssize_t n recv(fd, buf, sizeof(buf), 0); if (n 0) { // 读到了 n 字节 } else if (n 0) { // 对端关闭连接 } else { if (errno EAGAIN || errno EWOULDBLOCK) { // 现在没数据不是错误之后再读 } else { // 真正的错误 } }非阻塞 I/O 的核心就是要处理EAGAIN EWOULDBLOCK它们表示“现在做不了但不是致命错误”。六、accept 的阻塞和非阻塞accept用来接受新连接。阻塞模式下int client_fd accept(listen_fd, nullptr, nullptr);如果没有客户端连接进来程序就卡住。非阻塞模式下int client_fd accept(listen_fd, nullptr, nullptr);如果暂时没有新连接返回-1并且errno EAGAIN || errno EWOULDBLOCK所以非阻塞服务器里经常这样写while (true) { int client_fd accept(listen_fd, nullptr, nullptr); if (client_fd 0) { set_nonblocking(client_fd); // 加入 epoll } else { if (errno EAGAIN || errno EWOULDBLOCK) { break; } // 其他错误 break; } }这里的while很常见尤其是epoll的边缘触发模式下。七、 send/write 的阻塞和非阻塞很多人以为send一定能立刻把数据发出去其实不是。阻塞 socketsend(fd, data, len, 0);如果内核发送缓冲区满了send会卡住直到缓冲区有空间。非阻塞 socketssize_t n send(fd, data, len, 0);如果发送缓冲区满了它返回-1并设置errno EAGAIN || errno EWOULDBLOCK还有一个重要点send可能只发送一部分。比如你想发 10000 字节ssize_t n send(fd, data, 10000, 0);返回值可能是3000意思是只发出去了 3000 字节剩下 7000 字节要你之后继续发。所以非阻塞网络程序里一般要有发送缓冲区struct Connection { int fd; std::string write_buffer; };没发完的数据放进write_buffer等下次EPOLLOUT再发。八、connect 的阻塞和非阻塞connect也有区别。阻塞模式connect(fd, addr, len);会一直等到连接成功或失败。非阻塞模式下int ret connect(fd, addr, len);如果连接还在进行中通常返回-1并且errno EINPROGRESS意思是连接正在建立还没完成。这时你可以用epoll监听这个 fd 的可写事件EPOLLOUT等它可写时再用getsockopt检查是否连接成功。九、阻塞的问题阻塞本身不是坏事。简单程序里阻塞很好用while (true) { int client accept(listen_fd, nullptr, nullptr); recv(client, buf, sizeof(buf), 0); send(client, response, response_len, 0); }代码直观。但高并发服务器里阻塞会带来问题。假设一个线程处理一个连接10000 个连接 10000 个线程这会有线程创建成本高上下文切换成本高栈内存占用大调度开销大慢连接会占住线程如果一个客户端一直不发数据线程就一直卡在recv上。十、非阻塞的问题非阻塞也不是万能的。如果你这么写while (true) { ssize_t n recv(fd, buf, sizeof(buf), 0); if (n 0 errno EAGAIN) { continue; } }这会疯狂空转CPU 直接飙高。因为没有数据时你一直问有数据吗 没有。 有数据吗 没有。 有数据吗 没有。所以非阻塞 I/O 通常要配合select / poll / epoll也就是没有事件时睡眠 有事件时再尝试读写。这就是epoll的作用。十一、 epoll 和非阻塞的关系epoll通常配合非阻塞 fd 使用。典型流程把 socket 设为非阻塞 注册到 epoll epoll_wait 等事件 有 EPOLLIN 再 recv 读到 EAGAIN 停止 继续 epoll_wait代码结构像这样while (true) { int n epoll_wait(epfd, events, 1024, -1); for (int i 0; i n; i) { int fd events[i].data.fd; if (events[i].events EPOLLIN) { while (true) { ssize_t ret recv(fd, buf, sizeof(buf), 0); if (ret 0) { // 处理数据 } else if (ret 0) { // 对端关闭 close(fd); break; } else { if (errno EAGAIN || errno EWOULDBLOCK) { break; } close(fd); break; } } } } }这就是高性能网络编程里最经典的模式之一。

相关新闻

惠普暗影精灵笔记本终极性能控制工具:OmenSuperHub完整使用指南

惠普暗影精灵笔记本终极性能控制工具:OmenSuperHub完整使用指南

惠普暗影精灵笔记本终极性能控制工具:OmenSuperHub完整使用指南 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub …

2026/10/14 21:43:35 阅读更多 →
JavaWeb毕业设计全流程:从选题到答辩实战指南

JavaWeb毕业设计全流程:从选题到答辩实战指南

1. 编程类毕业设计全流程指导手册刚拿到毕业设计课题时的迷茫感我至今记忆犹新——面对空白的代码编辑器不知从何下手,在技术选型时反复纠结,调试时被一个报错卡住好几天。作为带过7届毕业设计的指导老师,今天就把完整的实战经验拆解成可落地…

2026/10/13 20:27:39 阅读更多 →
Keepalived高可用集群:VRRP协议与实战部署详解

Keepalived高可用集群:VRRP协议与实战部署详解

1. Keepalived 高可用集群:企业级服务的守护者第一次在生产环境部署Keepalived时,我盯着那台主服务器突然宕机的监控画面,心跳几乎停止——直到备用节点在1秒内自动接管了VIP(虚拟IP),所有服务请求无缝切换…

2026/10/12 7:08:28 阅读更多 →

最新新闻

AI Agent实战指南:从架构设计到工程落地的核心要点

AI Agent实战指南:从架构设计到工程落地的核心要点

1. 从"会聊天的模型"到"能办事的Agent":认知先对齐很多人第一次接触 AI Agent,脑子里浮现的还是那个对话框——你问一句,它答一句,答完就结束。但如果你真拿这种心态去搭 Agent,大概率会在第三天就…

2026/10/14 21:43:45 阅读更多 →
iOS社交应用如何通过App Store 4.3审核:从被拒原因到差异化避坑指南

iOS社交应用如何通过App Store 4.3审核:从被拒原因到差异化避坑指南

"4.3被拒了,App Store审核组说我的应用与其他应用存在大量雷同,属于垃圾应用。"这句话我今年已经听不止一个人说过了。社交应用是4.3的重灾区,不管你做的是兴趣社区、同城交友、泛娱乐聊天室还是垂直圈层App,只要你提交…

2026/10/14 21:43:45 阅读更多 →
HDFS架构原理与运维实战:从副本机制到Shell命令避坑指南

HDFS架构原理与运维实战:从副本机制到Shell命令避坑指南

HDFS这玩意儿在圈子里算得上"老贵族"了——平时不显山露水,但整个大数据生态的数据底座都压在它身上。不管是离线数仓的日分区清洗,还是实时链路落地的中间结果,最终都要老老实实落到HDFS的块上。这篇不聊教科书里那些干巴巴的定义…

2026/10/14 21:43:45 阅读更多 →
蓝桥杯省赛冲刺:一天掌握模拟、set与map的实战技巧

蓝桥杯省赛冲刺:一天掌握模拟、set与map的实战技巧

1. 写在最前面:这24小时到底该怎么用作为一个参加过好几届蓝桥杯、也带过不少学弟学妹临时抱佛脚的人,我先说句实话:如果你只剩一天,别指望学会所有的算法,但一定要把"模拟、set、map"这三个词焊死在脑子里。…

2026/10/14 21:43:45 阅读更多 →
TypeScript运行时校验实战:用impeccable给数据加一道保险

TypeScript运行时校验实战:用impeccable给数据加一道保险

上个月我负责的一个小工具上线没几天,就有用户反馈说页面打开是空白的。控制台报错指向Cannot read properties of undefined (reading name),追到根因后我发现:后端悄悄改了接口字段,而 TypeScript 的编译期检查在这里完全失效。…

2026/10/14 21:43:45 阅读更多 →
Android项目结构详解:从Gradle构建到App启动的完整认知

Android项目结构详解:从Gradle构建到App启动的完整认知

第一次用IDE创建Android项目时,我对着自动生成的一堆文件夹发了好一会儿呆。明明只想写一个“你好,世界”,可工程里却躺着settings.gradle、build.gradle、gradlew、local.properties,还有一个看起来很重要又不敢随便动的MainActi…

2026/10/14 21:42:43 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →