epoll使用例子
来源:互联网 发布:apache jmeter 3.1 编辑:程序博客网 时间:2024/04/29 05:31
名词解释:man epoll之后,得到如下结果:
NAME
epoll - I/O event notification facility
SYNOPSIS
#include <sys/epoll.h>
DESCRIPTION
epoll is a variant of poll(2) that can be used either as Edge or Level
Triggered interface and scales well to large numbers of watched fds.
Three system calls are provided to set up and control an epoll set:
epoll_create(2), epoll_ctl(2), epoll_wait(2).
An epoll set is connected to a file descriptor created by epoll_cre-
ate(2). Interest for certain file descriptors is then registered via
epoll_ctl(2). Finally, the actual wait is started by epoll_wait(2).
其实,一切的解释都是多余的,按照我目前的了解,EPOLL模型似乎只有一种格式,所以大家只要参考我下面的代码,就能够对EPOLL有所了解了,代码的解释都已经在注释中:
while (TRUE)
{
int nfds = epoll_wait (m_epoll_fd, m_events, MAX_EVENTS, EPOLL_TIME_OUT);//等待EPOLL时间的发生,相当于监听,至于相关的端口,需要在初始化EPOLL的时候绑定。
if (nfds <= 0)
continue;
m_bOnTimeChecking = FALSE;
G_CurTime = time(NULL);
for (int i=0; i<nfds; i++)
{
try
{
if (m_events[i].data.fd == m_listen_http_fd)//如果新监测到一个HTTP用户连接到绑定的HTTP端口,建立新的连接。由于我们新采用了SOCKET连接,所以基本没用。
{
OnAcceptHttpEpoll ();
}
else if (m_events[i].data.fd == m_listen_sock_fd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
{
OnAcceptSockEpoll ();
}
else if (m_events[i].events & EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。
{
OnReadEpoll (i);
}
OnWriteEpoll (i);//查看当前的活动连接是否有需要写出的数据。
}
catch (int)
{
PRINTF ("CATCH捕获错误\n");
continue;
}
}
m_bOnTimeChecking = TRUE;
OnTimer ();//进行一些定时的操作,主要就是删除一些短线用户等。
}
其实EPOLL的精华,按照我目前的理解,也就是上述的几段短短的代码,看来时代真的不同了,以前如何接受大量用户连接的问题,现在却被如此轻松的搞定,真是让人不得不感叹。
今天搞了一天的epoll,想做一个高并发的代理程序。刚开始真是郁闷,一直搞不通,网上也有几篇介绍epoll的文章。但都不深入,没有将一些注意的地方讲明。以至于走了很多弯路,现将自己的一些理解共享给大家,以少走弯路。
epoll用到的所有函数都是在头文件sys/epoll.h中声明,有什么地方不明白或函数忘记了可以去看一下。
epoll和select相比,最大不同在于:
1epoll返回时已经明确的知道哪个sokcet fd发生了事件,不用再一个个比对。这样就提高了效率。
2select的FD_SETSIZE是有限止的,而epoll是没有限止的只与系统资源有关。
1、epoll_create函数
函数声明:int epoll_create(int size)
该 函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket fd数。随你定好了。只要你有空间。可参见上面与select之不同2.
22、epoll_ctl函数
函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
该函数用于控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。
参数:
epfd:由 epoll_create 生成的epoll专用的文件描述符;
op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除
fd:关联的文件描述符;
event:指向epoll_event的指针;
如果调用成功返回0,不成功返回-1
用到的数据结构
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 */
};
如:
struct epoll_event ev;
//设置与要处理的事件相关的文件描述符
ev.data.fd=listenfd;
//设置要处理的事件类型
ev.events=EPOLLIN|EPOLLET;
//注册epoll事件
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
常用的事件类型:
EPOLLIN :表示对应的文件描述符可以读;
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET:表示对应的文件描述符有事件发生;
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事件发生的超时值(单位我也不太清楚);-1相当于阻塞,0相当于非阻塞。一般用-1即可
返回发生事件数。
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <openssl/ssl.h>
- #include <openssl/err.h>
- #include <fcntl.h>
- #include <sys/epoll.h>
- #include <sys/time.h>
- #include <sys/resource.h>
- #define MAXBUF 1024
- #define MAXEPOLLSIZE 10000
- /*
- setnonblocking - 设置句柄为非阻塞方式
- */
- int setnonblocking(int sockfd)
- {
- if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)
- {
- return -1;
- }
- return 0;
- }
- /*
- handle_message - 处理每个 socket 上的消息收发
- */
- int handle_message(int new_fd)
- {
- char buf[MAXBUF + 1];
- int len;
- /* 开始处理每个新连接上的数据收发 */
- bzero(buf, MAXBUF + 1);
- /* 接收客户端的消息 */
- len = recv(new_fd, buf, MAXBUF, 0);
- if (len > 0)
- {
- printf
- ("%d接收消息成功:'%s',共%d个字节的数据\n",
- new_fd, buf, len);
- }
- else
- {
- if (len < 0)
- printf
- ("消息接收失败!错误代码是%d,错误信息是'%s'\n",
- errno, strerror(errno));
- close(new_fd);
- return -1;
- }
- /* 处理每个新连接上的数据收发结束 */
- return len;
- }
- /************关于本文档********************************************
- *filename: epoll-server.c
- *purpose: 演示epoll处理海量socket连接的方法
- *wrote by: zhoulifa(<a href="mailto:zhoulifa@163.com"& gt;zhoulifa@163.com</a>) 周立发(<a href="http: //zhoulifa.bokee.com">http://zhoulifa.bokee.com</a>)
- Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
- *date time:2007-01-31 21:00
- *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
- * 但请遵循GPL
- *Thanks to:Google
- *Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
- * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
- *********************************************************************/
- int main(int argc, char **argv)
- {
- int listener, new_fd, kdpfd, nfds, n, ret, curfds;
- socklen_t len;
- struct sockaddr_in my_addr, their_addr;
- unsigned int myport, lisnum;
- struct epoll_event ev;
- struct epoll_event events[MAXEPOLLSIZE];
- struct rlimit rt;
- myport = 5000;
- lisnum = 2;
- /* 设置每个进程允许打开的最大文件数 */
- rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
- if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
- {
- perror("setrlimit");
- exit(1);
- }
- else
- {
- printf("设置系统资源参数成功!\n");
- }
- /* 开启 socket 监听 */
- if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)
- {
- perror("socket");
- exit(1);
- }
- else
- {
- printf("socket 创建成功!\n");
- }
- setnonblocking(listener);
- bzero(&my_addr, sizeof(my_addr));
- my_addr.sin_family = PF_INET;
- my_addr.sin_port = htons(myport);
- my_addr.sin_addr.s_addr = INADDR_ANY;
- epoll使用例子
- epoll使用例子
- epoll使用例子
- epoll使用例子
- epoll使用例子
- epoll的使用例子
- epoll 使用简单例子
- Epoll例子的使用
- 一个简单的epoll使用例子
- python使用epoll实现的服务端例子
- python使用epoll实现的服务端例子
- epoll 例子
- epoll例子
- EPOLL例子
- epoll例子
- epoll使用的一个小例子,非常实用
- epoll使用的一个小例子,非常实用
- 一个小例子演示下epoll和管道的使用
- 交换机转发过滤技术提高网络安全性能
- 【源码分享】马上有短信
- 中指无名指收起 其他3个手指伸出来 这种手势是什么意思?
- UVA 11762 - Race to 1(概率)
- 获取数据库中订单信息
- epoll使用例子
- 回收站已经清空了,怎么才能找回被删掉的文件
- Qt4的项目迁移到qt5
- Android 网络编程 API笔记 - java.net 包相关 接口 api
- 取整函数
- 发的客观和人家觉得房管局科技的股份
- 正则表达式
- C# Lambda表达式理解
- 素数,互素