epoll用到的所有函数都是在头文件sys/epoll.h中声明的,下面简要说明所用到的数据结构和函数:
所用到的数据结构
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件,其中epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据,例如一个client连接到服务器,服务器通过调用accept函数可以得到于这个client对应的socket文件描述符,可以把这文件描述符赋给epoll_data的fd字段以便后面的读写操作在这个文件描述符上进行。epoll_event 结构体的events字段是表示感兴趣的事件和被触发的事件可能的取值为:EPOLLIN :表示对应的文件描述符可以读;
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(我不太明白是什么意思,可能是类似client关闭 socket连接这样的事件);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET:表示对应的文件描述符有事件发生;
所用到的函数:
1、epoll_create函数
函数声明:int epoll_create(int size)
该函数生成一个epoll专用的文件描述符,其中的参数是指定生成描述符的最大范围(我觉得这个参数和select函数的第一个参数应该是类似的但是该怎么设置才好,我也不太清楚)。
2、epoll_ctl函数
函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
该函数用于控制某个文件描述符上的事件,可以注册事件,修改事件,删除事件。
参数:epfd:由 epoll_create 生成的epoll专用的文件描述符;
op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修
改、EPOLL_CTL_DEL 删除
fd:关联的文件描述符;
event:指向epoll_event的指针;
如果调用成功返回0,不成功返回-1
3、epoll_wait函数
函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
该函数用于轮询I/O事件的发生;
参数:
epfd:由epoll_create 生成的epoll专用的文件描述符;
epoll_event:用于回传代处理事件的数组;
maxevents:每次能处理的事件数;
timeout:等待I/O事件发生的超时值;
返回发生事件数。
例子:
代码:
#include <iostream>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define MAXLINE 10
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 5555
#define INFTIM 1000
void setnonblocking(int sock)
{
int opts;
opts=fcntl(sock,F_GETFL);
if(opts<0)
{
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0)
{
perror("fcntl(sock,SETFL,opts)");
exit(1);
}
}
int main()
{
int i, maxi, listenfd, connfd, sockfd,epfd,nfds;
ssize_t n;
char line[MAXLINE];
socklen_t clilen;
//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
struct epoll_event ev,events[20];
//生成用于处理accept的epoll专用的文件描述符
epfd=epoll_create(256);
struct sockaddr_in clientaddr;
struct sockaddr_in serveraddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
//把socket设置为非阻塞方式
setnonblocking(listenfd);
//设置与要处理的事件相关的文件描述符
ev.data.fd=listenfd;
//设置要处理的事件类型
ev.events=EPOLLIN|EPOLLET;
//注册epoll事件
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
char *local_addr="200.200.200.204";
inet_aton(local_addr,&(serveraddr.sin_addr));//htons(SERV_PORT);
serveraddr.sin_port=htons(SERV_PORT);
bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
listen(listenfd, LISTENQ);
maxi = 0;
for ( ; ; ) {
//等待epoll事件的发生
nfds=epoll_wait(epfd,events,20,500);
//处理所发生的所有事件
for(i=0;i<nfds;++i)
{
if(events[i].data.fd==listenfd)
{
connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
if(connfd<0){
perror("connfd<0");
exit(1);
}
setnonblocking(connfd);
char *str = inet_ntoa(clientaddr.sin_addr);
std::cout<<"connect from "<_u115 ?tr<<std::endl;
//设置用于读操作的文件描述符
ev.data.fd=connfd;
//设置用于注测的读操作事件
ev.events=EPOLLIN|EPOLLET;
//注册ev
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
}
else if(events[i].events&EPOLLIN)
{
if ( (sockfd = events[i].data.fd) < 0) continue;
if ( (n = read(sockfd, line, MAXLINE)) < 0) {
if (errno == ECONNRESET) {
close(sockfd);
events[i].data.fd = -1;
} else
std::cout<<"readline error"<<std::endl;
} else if (n == 0) {
close(sockfd);
events[i].data.fd = -1;
}
//设置用于写操作的文件描述符
ev.data.fd=sockfd;
//设置用于注测的写操作事件
ev.events=EPOLLOUT|EPOLLET;
//修改sockfd上要处理的事件为EPOLLOUT
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
else if(events[i].events&EPOLLOUT)
{
sockfd = events[i].data.fd;
write(sockfd, line, n);
//设置用于读操作的文件描述符
ev.data.fd=sockfd;
//设置用于注测的读操作事件
ev.events=EPOLLIN|EPOLLET;
//修改sockfd上要处理的事件为EPOLIN
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
}
}
}
分享到:
相关推荐
### Epoll模型详解 #### 一、Epoll概述 在Linux网络编程中,早期广泛使用的事件触发机制主要是基于`select`。然而随着技术的发展以及应用需求的提高,`select`逐渐暴露出了一些明显的局限性,比如它对于大量文件...
`epoll`模型是解决高并发服务器性能瓶颈的有效手段之一,它比传统的`select`和`poll`模型更加先进,能够更有效地管理和监控文件描述符(FDs)的状态变化。 `epoll`的核心概念包括`epoll_create`、`epoll_ctl`和`...
网络编程中的`epoll`模型是Linux操作系统提供的一种高效、高性能的I/O多路复用技术,主要用于管理和调度大量的并发连接。在这个模型中,`epoll`替代了传统的`select`和`poll`,解决了它们在处理大量文件描述符时性能...
epoll模型作为Linux提供的一种I/O多路复用技术,正是为了解决这一问题而设计的。本文将深入探讨epoll的工作原理、优势以及如何在实际编程中运用。 epoll,全称Event Poll,它是基于文件描述符(file descriptor)的...
epoll反应堆模型代码,相对于网上普通的epoll模型增加了send recv 操作,并有详细的注释epoll反应堆
接下来,我们讨论epoll模型。epoll是Linux系统提供的一种高效I/O事件通知机制,尤其适用于高并发的网络服务器。它替代了传统的select和poll,解决了它们在大量文件描述符时性能下降的问题。epoll通过内核用户空间...
Epoll模型相比传统的select、poll等I/O多路复用模型,具有更好的性能和可扩展性。这个"linux下Epoll模型实例代码"是一个展示如何在Linux环境下使用Epoll进行I/O事件监控的程序示例。 Epoll的核心概念包括以下几个...
epoll模型http server
《Epoll模型详解》 在Linux的网络编程领域,Epoll模型是替代传统select模型的一种高效解决方案。Epoll的优势在于其高效性和可扩展性,它避免了随着监听文件描述符(fd)数量增加而导致的性能下降问题。传统的select...
《深入理解Epoll模型在Linux网络编程中的应用》 在Linux的网络编程中,Epoll模型作为select模型的替代方案,具有显著的性能优势。Epoll的出现解决了select在面对大量文件描述符(FD)时效率低下的问题,它通过高效...
《Epoll模型详解》 Epoll是Linux内核提供的一种高效、可扩展的I/O事件通知机制,尤其在处理大量并发连接时表现出显著优势。它替代了传统的select和poll方法,解决了这些方法在处理大量文件描述符(fd)时效率低下的...
### EPOLL模型:关于并发连接的处理 #### 一、Select 的局限性 在 Linux 内核中,`select` 是一种常用的 I/O 多路复用机制,它允许一个进程监控多个文件描述符(FD),并在这些 FD 就绪(例如可读或可写)时通知...
用思维导图的方式总结了Epoll模型,非常的好理解。文件需要用MindMange打开。
2. **EPOLL模型**:在`epoll`中,主要有三个关键函数:`epoll_create`、`epoll_ctl`和`epoll_wait`。 - `epoll_create`:创建一个`epoll`实例,返回一个描述符。 - `epoll_ctl`:用于管理和修改`epoll`实例中的...
在Android系统中,Epoll模型是一种高效的I/O多路复用技术,主要用于处理大量的并发连接。JNI(Java Native Interface)是Java平台标准的一部分,它允许Java代码和其他语言写的代码进行交互。当我们需要在Android应用...
**EPOLL模型详解** Linux 2.6内核引入了EPOLL模型,作为解决I/O多路复用问题的一种高效机制,特别是在处理大量socket描述符(FD)时。EPOLL对比传统的select和poll模型,具有以下显著优点: 1. **不受FD数量限制**...
Linux下的epoll模型是高效处理I/O事件的一种机制,尤其在高并发的网络服务中表现卓越。epoll是由早期的poll和select模型发展而来,它提供了更优秀的性能和可扩展性。在这里,我们有两个示例服务器模型:mychat和...
本教程将深入探讨如何利用socket编程、epoll模型、线程池、心跳检测以及工厂模式来搭建这样的服务器,并且提供了客户端的测试代码。以下是对这些知识点的详细解释: 1. **Linux Socket编程**: Linux Socket是进程...
myserver是一个基于epoll模型的异步通信、返回结果为JSON的高性能服务器。它使用C 编写,需要通过mylog以及myconf这二者做编译依赖。和外界交互为JSON格式(使用开源库rapidjson)。用户只需要配置好服务器,开始...