在之前的文章中提到过Readn 函数:

ssize_t Readn(int fd, void *vptr, size_t n)

试想这样一种情况:
1、server 循环使用 epoll_wait,监听 fd,fd 发生读事件,epoll_wait 通知 server。
2、server 接到通知,调用 Readn 函数,读取 500 字节。
3、但是,client 就发送了 200 字节,不足 500 字节。
4、此时,server 会阻塞在 Readn 函数上。
5、意味着 server 无法执行下一次 epoll_wait,意味着即使 client 再给 server 发数据,server 也得不到通知。
6、server 得不到通知,就无法读数据,就无法解除 Readn 函数的阻塞。
结果:造成“死锁”现象。
解决:将“套接字的文件描述符”设置为非阻塞 。

int flag = fcntl(cfd, F_GETFL); // 获得文件原属性
flag |= O_NONBLOCK; // 添加非阻塞属性
fcntl(connfd, F_SETFL, flag); // 使非阻塞属性生效

epoll的“边沿模式”下的“非阻塞读”模型

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#define MAXLINE 10
#define SERV_PORT 8000
int main(void)
{struct sockaddr_in servaddr;socklen_t cliaddr_len;int listenfd, connfd;char buf[MAXLINE];char str[INET_ADDRSTRLEN];int efd, flag;listenfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); // 绑定端口和IPlisten(listenfd, 20); // 设置同时访问上限数struct epoll_event event; // epoll_ctl 传入参数struct epoll_event resevent[10]; // epoll_wait 传出参数int res, len;efd = epoll_create(10); // 创建epoll树根event.events = EPOLLIN | EPOLLET; /* ET 边沿触发,默认是水平触发 */printf("Accepting connections ...\n");truct sockaddr_in cliaddr;cliaddr_len = sizeof(cliaddr);connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); // 阻塞等待连接,获得connfdprintf("received from %s at PORT %d\n",inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),ntohs(cliaddr.sin_port)); // 获得客户端信息flag = fcntl(connfd, F_GETFL); /* 修改connfd为非阻塞读 */ // connfd 设置为非阻塞flag |= O_NONBLOCK;fcntl(connfd, F_SETFL, flag);event.data.fd = connfd; // 至此epoll_ctl 传入参数设置完毕epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &event); // 将connfd加入监听红黑树while (1) {printf("epoll_wait begin\n");res = epoll_wait(efd, resevent, 10, -1); // 最多10个, 阻塞监听printf("epoll_wait end res %d\n", res);if (resevent[0].data.fd == connfd) {while ((len = read(connfd, buf, MAXLINE / 2)) > 0) write(STDOUT_FILENO, buf, len); }}return 0;
}
// 如果是 非阻塞,边沿触发:read 不会阻塞,wait 只调用 1 次,while 循环 2 次
// 如果是 非阻塞,水平触发:read 不会阻塞,wait 需调用 2 次,while 循环 2 次

epoll 边沿触发 非阻塞 IO 服务器相关推荐

  1. java epoll select_Java 非阻塞 IO 和异步 IO

    点击上方 Java后端,选择 设为星标 优质文章,及时送达 作者 | HongJie 链接 | javadoop.com/post/nio-and-aio 本文将介绍非阻塞 IO 和异步 IO,也就是 ...

  2. 聊聊对不同I/O模型的理解 (阻塞/非阻塞IO,同步/异步IO)

    一.关于I/O模型的问题 最近通过对ucore操作系统的学习,让我打开了操作系统内核这一黑盒子,与之前所学知识结合起来,解答了长久以来困扰我的关于I/O的一些问题. 1. 为什么redis能以单工作线 ...

  3. python3 异步 非阻塞 IO多路复用 select poll epoll 使用

    有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理还是有必要的. 下面记录下分别基于Select/Poll/Epoll的echo ser ...

  4. 实例浅析epoll的水平触发和边缘触发,以及边缘触发为什么要使用非阻塞IO

    一.基本概念 我们通俗一点讲: Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写.如果这次没有把数据一次性全部读写完( ...

  5. Python异步非阻塞IO多路复用Select/Poll/Epoll使用

    来源:http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理 ...

  6. 为何 epoll 的 ET 模式一定要设置为非阻塞IO

    ET模式下每次write或read需要循环write或read直到返回EAGAIN错误.以读操作为例,这是因为ET模式只在socket描述符状态发生变化时才触发事件,如果不一次把socket内核缓冲区 ...

  7. Linux 阻塞和非阻塞IO 实验

    目录 阻塞和非阻塞IO 阻塞和非阻塞简介 等待队列 轮询 Linux 驱动下的poll 操作函数 阻塞IO 实验 硬件原理图分析 实验程序编写 运行测试 非阻塞IO 实验 硬件原理图分析 实验程序编写 ...

  8. Linux之阻塞与非阻塞IO

    目录 一.阻塞与非阻塞IO简介 1.阻塞IO 2.非阻塞IO 二.应用程序阻塞与非阻塞 1.阻塞 2.查询(非阻塞) ①select ②poll ③epoll 三.驱动程序阻塞与非阻塞 1.等待队列( ...

  9. Redis 笔记(12)— 单线程架构(非阻塞 IO、多路复用)和多个异步线程

    Redis 使用了单线程架构.非阻塞 I/O .多路复用模型来实现高性能的内存数据库服务.Redis 是单线程的.那么为什么说是单线程呢? Redis 在 Reactor 模型内开发了事件处理器,这个 ...

最新文章

  1. 备份一张iPhone拍照写入exif中的orientation图片
  2. JSP学习笔记04-request
  3. spring IOC容器的扩展
  4. *30.什么是微内核
  5. 阿里巴巴DevOps实践指南 | 数字化转型下,DevOps的根本目标是什么?
  6. 怎么汇报一周开发工作情况_如何在没有经验的情况下获得第一份开发人员工作
  7. tinyxml初体验
  8. springmvc源码-参数解析
  9. 政府信息化与电子政务
  10. 整个AppData目录挪到D盘方法
  11. 淦!为什么到处都是广告!
  12. 推理时 cnn bn 折叠;基于KWS项目
  13. 员工奖金需要交税吗_定了!年终奖必须这样缴税!国家税务局终于明确。
  14. C#·Excel拉取日期格式的数据
  15. 0.1.3-01 合宙CORE-ESP32-C3制作1.3寸ST7789驱动的简单相册
  16. go开发虚拟串口服务器,vspd.go
  17. Mysql数据库使用规范
  18. 数值积分法(1)————欧拉法
  19. java 创建mdi窗体_Java制作MDI窗体源代码是什么?
  20. 什么是领域模型?什么是数据模型

热门文章

  1. 北京内推 | 启元实验室招聘视觉感知算法工程师(北京事业单位)
  2. 今晚直播 | ICML 2021论文解读:基于Cox-MLP模型的二阶段共形预测
  3. ICML 2020 | 基于类别描述的文本分类模型
  4. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task5:模型训练与验证
  5. 打印Show Attend and Tell的损失函数
  6. PyTorch-torch.nn.AdaptiveAvgPool2d
  7. 从零学习SwinTransformer
  8. python知识点总结(有空就往里面添加)
  9. linux操作这样用视频,Linux下使用mencoder对视频进行操作
  10. 【Java报错】借助@PostConstruct解决使用@Component注解的类用@Resource注入Mapper接口为null的问题(原因解析+解决方法)