发布时间:2026/8/7 1:07:00
阻塞和非阻塞 “阻塞”和“非阻塞”主要是在说当一个操作暂时无法完成时调用者是停在那里等还是立刻返回。它经常出现在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; } } } } }这就是高性能网络编程里最经典的模式之一。

相关新闻

2026/8/7 1:07:00

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

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

2026/8/7 1:07:00

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

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

2026/8/7 1:57:04

Flutter ipwhois库鸿蒙适配实战与性能优化

1. 项目背景与核心价值在移动应用开发领域,网络溯源和地理位置服务一直是刚需功能。传统的IP查询方案往往存在平台兼容性差、数据维度单一等问题。而ipwhois作为Flutter生态中功能最全面的IP信息查询库,原生支持ASN(自治系统号)查询、地理位置元数据获取…

2026/8/7 1:57:04

深入解析浮点四则运算:从IEEE 754标准到工程实践

1. 从“算不准”到“算得对”:浮点运算的工程挑战如果你写过一段简单的代码,比如在Python里计算0.1 0.2,然后满怀期待地打印结果,大概率会看到一个让你有点懵的数字:0.30000000000000004。这并非Python的bug&#xff…

2026/8/7 1:57:04

米思齐图形化编程驱动2.8寸屏:嵌入式快速原型开发实战

最近在整理一些小型嵌入式项目时,发现一个挺有意思的现象:很多朋友拿到一块带屏幕的开发板,比如那种小巧的2.8寸屏,第一反应是找Arduino IDE写代码,然后对着屏幕驱动库的复杂API发愁。画个界面、显示个数据&#xff0c…

2026/8/7 1:57:04

如何快速上手Akebi-GC:原神智能辅助工具完全指南

如何快速上手Akebi-GC:原神智能辅助工具完全指南 【免费下载链接】Akebi-GC (Fork) The great software for some game that exploiting anime girls (and boys). 项目地址: https://gitcode.com/gh_mirrors/ak/Akebi-GC 还在为《原神》中繁琐的资源收集和重…

2026/8/7 1:52:04

Windows系统无损迁移实战:从原理到避坑的完整指南

1. 从“重装”到“迁移”:一次完整的Windows系统搬家实战如果你和我一样,是个重度依赖Windows环境进行开发、设计或日常办公的用户,那么“重装系统”这个词,大概率会带来一阵头皮发麻的恐惧。这不仅仅意味着要花上半天甚至一天的时…

2026/8/5 3:13:11

如何用免费工具突破游戏窗口限制:SRWE完整使用指南

如何用免费工具突破游戏窗口限制:SRWE完整使用指南 【免费下载链接】SRWE Simple Runtime Window Editor 项目地址: https://gitcode.com/gh_mirrors/sr/SRWE 你是否遇到过这样的困扰?想为心爱的游戏截图,却发现游戏不支持自定义分辨率…

2026/8/7 0:01:55

CAD图库管理:从文件归档到设计资产管理的效率革命

你肯定遇到过这种情况:打开一个老项目,想找某个特定的图块——比如一个标准的门、一个特定的设备符号,或者一个公司logo。你记得它就在某个DWG文件里,或者曾经从某个同事那里拷来过。于是,你开始在一堆命名混乱的文件夹…

2026/8/7 0:01:55

5分钟掌握Wand-Enhancer:2026年终极WeMod专业版免费解锁指南

5分钟掌握Wand-Enhancer:2026年终极WeMod专业版免费解锁指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand-Enhancer是一款功能强…

2026/8/7 0:01:55

“Quality Control(质量控制)”在软件工程中通常指通过一系列活动确保软件产品符合预定的质量标准和用户需求

“Quality Control(质量控制)”在软件工程中通常指通过一系列活动确保软件产品符合预定的质量标准和用户需求。而“软件测试”是质量控制的关键手段之一,属于QC范畴下的具体实践,其目标是发现缺陷、验证功能正确性、评估软件质量属…

2026/8/5 19:21:13

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/5 19:21:13

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/6 20:45:01

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…