这里写目录标题

  • 什么是epoll?
  • epoll API
    • 头文件
    • 创建句柄
    • epoll控制函数
    • epoll消息读取
    • 代码示例

什么是epoll?

epoll接口是为解决Linux内核处理大量文件描述符而提出的方案。该接口属于Linux下多路I/O复用接口中select/poll的增强。其经常应用于Linux下高并发服务型程序,特别是在大量并发连接中只有少部分连接处于活跃下的情况 (通常是这种情况),在该情况下能显著的提高程序的CPU利用率。

目前epell是linux大规模并发网络程序中的热门首选模型。
epoll除了提供 select/ poll那种 IO事件的电平触发(Level Triggered)外,还提
供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存 IO状态,减少
epoll_wait/epoll_pwait的调用,提高应用程序效率。

EPOLL 事件有两种模型:
Edge Triggered (ET) 边缘触发 只有新数据到来,才触发,不管缓存区中是否还有数据。
Level Triggered (LT) 水平触发 只要有数据都会触发,不管数据是哪里的。

epoll API

头文件

#include<sys/epoll.h>

创建句柄

int epoll_create(int size)
size:告诉内核监听的数目

创建一个epoll句柄,参数size用于告诉内核监听的文件描述符个数,跟内存大小有关。
返回epoll 文件描述符

epoll控制函数

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event );// 成功,返0,失败返-1

epfd:为epoll_creat的句柄
op:表示动作,用3个宏来表示:
···EPOLL_CTL_ADD(注册新的fd到epfd),
···EPOLL_CTL_MOD(修改已经注册的fd的监听事件),
···EPOLL_CTL_DEL(从epfd删除一个fd);
event:告诉内核需要监听的事件

struct epoll_event
{__uint32_t events;  /* epoll event */epoll_data_t data;  /* User data variable */
};typedef union epoll_data
{void* ptr;int fd;__uint32_t u32;__uint64_t u64;
} epoll_data_t;  /* 保存触发事件的某个文件描述符相关的数据 *//* epoll_event.events:EPOLLIN  表示对应的文件描述符可以读EPOLLOUT 表示对应的文件描述符可以写EPOLLPRI 表示对应的文件描述符有紧急的数据可读EPOLLERR 表示对应的文件描述符发生错误EPOLLHUP 表示对应的文件描述符被挂断EPOLLET  表示对应的文件描述符有事件发生
*/

epoll消息读取

//等待所监控文件描述符上有事件的产生,类似于select()调用。
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);events:用来从内核得到事件的集合,
maxevents:告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,
timeout:是超时时间
-1:阻塞
0:立即返回,非阻塞
>0:指定微秒
返回值:成功返回有多少文件描述符就绪,时间到时返回0,出错返回-1

代码示例

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include<sys/epoll.h>
#include<errno.h>#define MAXLINE 80
#define SERV_PORT 8000
#define OPEN_MAX 1024int main()
{struct sockaddr_in servaddr,cliaddr;socklen_t cliaddr_len;int i,j,maxi,maxfd,listenfd,connfd,sockfd;int nready,efd,res,client[OPEN_MAX];ssize_t n;char buf[MAXLINE];char sendbuf[MAXLINE];char str[INET_ADDRSTRLEN];struct epoll_event tep,ep[OPEN_MAX];listenfd = socket(AF_INET,SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);servaddr.sin_addr.s_addr = htonl(INADDR_ANY);bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));listen(listenfd,20); //把先完成三次握手的客户端加入到队列之中maxfd = listenfd;maxi = -1;for(i = 0 ; i < OPEN_MAX ; i++ )client[i] = -1;//用-1初始化clientefd = epoll_create(OPEN_MAX); //创建句柄tep.events = EPOLLIN;  //设置读事件tep.data.fd = listenfd; //套接socket文件描述符res = epoll_ctl(efd,EPOLL_CTL_ADD,listenfd,&tep);//将listenfd加入监听文件表,监听listenfd的读取内容if(res == -1)perror("epoll_ctl");while(1){nready = epoll_wait(efd,ep,OPEN_MAX,-1);//阻塞监听if(nready == -1)perror("epoll_wait error:");for(i=0;i<nready; i++){if(!ep[i].events & EPOLLIN) //判断是否EPOLLINcontinue;if(ep[i].data.fd == listenfd){//开始接收数据printf("Accepting connections num:%d \n",i+1); cliaddr_len = sizeof(cliaddr);connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); //接收连接 就是把最先已经完成三次握手的客户端提取出来printf("Read from %s at port %d \n",inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),ntohs(cliaddr.sin_port));//将客户端的地址、端口号转换成整形数输出for(j = 0;j < OPEN_MAX; j++){if(client[j] < 0){client[j] = connfd;//保存accept返回的文件描述符到client[]里break;}if( j == OPEN_MAX ){printf("Too many clients \n",stderr);exit(-1);}if(j > maxi)maxi = j;}tep.events = EPOLLIN;tep.data.fd = connfd;res = epoll_ctl(efd,EPOLL_CTL_ADD,connfd,&tep);  //将connfd加入监听文件表,监听connfd的读取内容if(res == -1)perror("epoll_ctl");}else{sockfd = ep[i].data.fd;n = read(sockfd,buf,MAXLINE);printf("client data:\n");printf(" %s\n",buf);if(n == 0){for(j = 0 ; j <= maxi ; j++){if(client[i] == sockfd){client[j] = -1;break;}}res = epoll_ctl(efd,EPOLL_CTL_ADD,sockfd,&tep); //将sockfd加入监听文件表,监听sockfd的读取内容if(res == -1)perror("epoll_ctl");close(sockfd);printf("Client[%d] closed connetion \n",j);}else{for(j = 0; j<n; j++)buf[j] = toupper(buf[j]);printf("server write data:\n");printf(" %s\n",buf);write(sockfd,buf,n);memset(buf,0,sizeof(buf));}}}close(listenfd);close(efd);return 0;
}

多路I/O转接服务器——epoll相关推荐

  1. LinuxI/O多路复用转接服务器——epoll模型实现

    LinuxI/O多路复用转接服务器--epoll模型实现 epoll函数 epoll函数组 epoll_create函数 epoll_ctl函数 epoll_wait函数 epoll实现实现I/O多路 ...

  2. linux网络编程之多路I/O转接服务器poll函数

    (1)poll函数 头文件:#include<poll.h> int  poll(struct  pollfd*fds, nfds_t nfds,int timeout); struct  ...

  3. linux网络编程之多路I/o转接服务器select

    (1)多路IO转接服务器也叫做多任务IO服务器,其主要思想是不再由程序自己监听客户端连接,取而代之的是由内核替应用程序监视文件,具体实现模型如图所示: 当客户端请求和服务器连接时,内核接收到连接指令, ...

  4. 多路IO转接服务器 epoll

    创建一个epoll句柄,参数size用来告诉内核监听的文件描述符的个数,跟内存大小有关. #include <sys/epoll.h> int epoll_create(int size) ...

  5. IO多路转接之epoll

    IO多路转接之epoll 文章目录 IO多路转接之epoll 一.epool 二.基于epoll实现服务器(LT) 三.**基于epoll实现服务器(LT)** 一.epool 是为处理大批量句柄而作 ...

  6. 网络编程(三)TCP IO多路转接服务器编程(select)

    同系列文章: 1, 文章目录 一,select知识引入 二,select基本概念 2.1 select概念理解前先总结一下通信过程(便于后文理解select) 2.2 select函数的用法 2.2. ...

  7. IO多路转接模型-----epoll

    epoll: Linux下性能最高的多路转接模型 epoll 有3个相关的系统调用. epoll_create 功能:创建epoll,在内核中创建eventpoll结构体,size决定了epoll最多 ...

  8. LinuxI/O多路复用转接服务器——poll模型实现

    LinuxI/O多路复用转接服务器--poll模型实现 poll函数 函数原型 参数和返回值 poll实现实现I/O多路复用服务器 实现流程 程序实现 服务端程序 客户端程序 运行结果 poll优缺点 ...

  9. LinuxI/O多路复用转接服务器——select模型实现

    LinuxI/O多路复用转接服务器--select模型实现 select函数 函数原型 参数和返回值 fd_set结构体 位操作函数 select实现实现I/O多路复用服务器 实现流程 程序实现 服务 ...

最新文章

  1. 每日一皮:不同的视角看待问题...
  2. https跨域到http问题解决
  3. Beaker 1.6.4 : Python Package Index
  4. tf.Variable 和 tf.get_variable的区别(2)
  5. linux操作系统信号捕捉函数之回调函数小结
  6. python字符串怎么用_零基础如何使用python处理字符串?
  7. 初步学习pg_control文件之六
  8. python中shift_Pandas DataFrame.shift()用法示例
  9. 远程调用python_远的解释|远的意思|汉典“远”字的基本解释
  10. spark读写hive数据
  11. 微软复合文档二进制格式实例分析
  12. css3做各种角度三角形
  13. flutter混编ios打包生成ipa文件
  14. 固体或液体体积与分子势能的关系——摘自《中学物理教学参考》
  15. 超火的微信小说小程序源码+比较轻量级/UI不错
  16. 学计算机的考研考教育学好考吗,2011年考研心路:我的两年教育学考研总结
  17. 实用工具网站(搜索/PPT/图片操作...)
  18. python中如何打印阶梯_python 阶梯图
  19. DDD解决软件系统腐化之道
  20. java工程师知识架构图图_阿里技术专家教你画架构图、Java 工程师成神之路 | 2019 年 2 月收藏排行...

热门文章

  1. ttlink无线打印服务器固件,TTLINK TT-180U1打印机服务器 TCP/IP添加打印机的教程
  2. 机器学习之数学基础(四)~Lasso Regression回归, L1、L2 Regularization正则化, 回归问题中的损失函数
  3. Tableau实战系列Tableau基础概念全解析 (二)-万字长文解析数据类型及数据集
  4. ubuntu系统在vmware中无法联网问题解决
  5. python怎么把程序封装成函数_PYTHON中如何把固定格式代码,封装成一个函数?
  6. MapReduce工作流理解
  7. Agisoft PhotoScan Professional软件处理无人机航拍照片基本流程
  8. 【LeetCode从零单排】No198.House Robber No91.Decode Ways139 word break(动态规划典型应用)
  9. android图文介绍NDK安装及简单jni demon的实现
  10. 机器学习实战读书笔记--朴素贝叶斯