epoll学习

一、epoll_create

#include <sys/epoll.h>int epoll_create(int size);
int epoll_create1(int flags);
返回:成功非负文件描述符,-1出错
size:内核监听数目一共多大

创建一个epoll接口,size参数和select不同,不是fd+1?

需要注意的是:当创建好epoll后,它就会占用一个fd值,在linux /proc/id/fd/能看到这个fd的,所以使用完epoll后,必须close()关闭,否则可能导致耗尽fd。

 

二、epoll_ctl

#include <sys/epoll.h>int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
返回:0成功,-1失败
epfd:由epoll_create生成的epoll专用的文件描述符
op:要进行的操作,可能取EPOLL_CTL_ADD注册、EPOLL_CTL_MOD修改、EPOLL_CTL_DEL删除
fd:关联的文件描述符
event:指向epoll_event指针

 epoll的相关的epoll_event结构:

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 */
};

其中的events可以是以下几个宏的集合:

EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

三、epoll_wait

#include <sys/epoll.h>int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);int epoll_pwait(int epfd, struct epoll_event *events,int maxevents, int timeout, const sigset_t *sigmask);
返回:发生事件数
epfd:由epoll_create生成的epoll专用的文件描述符
epoll_event:用于回传代处理事件的数组
maxevents:每次能处理的事件数
timeout:等待I/O事件发生的超时值

 

在linux中的man手册中有epoll模型:

 1            #define MAX_EVENTS 10
 2            struct epoll_event ev, events[MAX_EVENTS];
 3            int listen_sock, conn_sock, nfds, epollfd;
 4 
 5            /* Set up listening socket, 'listen_sock' (socket(),
 6               bind(), listen()) */
 7 
 8            epollfd = epoll_create(10);
 9            if (epollfd == -1) {
10                perror("epoll_create");
11                exit(EXIT_FAILURE);
12            }
13 
14            ev.events = EPOLLIN;
15            ev.data.fd = listen_sock;
16            if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
17                perror("epoll_ctl: listen_sock");
18                exit(EXIT_FAILURE);
19            }
20 
21            for (;;) {
22                nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);  //等待IO事件
23                if (nfds == -1) {
24                    perror("epoll_pwait");
25                    exit(EXIT_FAILURE);
26                }
27 
28                for (n = 0; n < nfds; ++n) {
29                //如果是主socket事件,则表示有新连接进入,需要进行新连接的处理
30                    if (events[n].data.fd == listen_sock) {
31                        conn_sock = accept(listen_sock,
32                                        (struct sockaddr *) &local, &addrlen);
33                        if (conn_sock == -1) {
34                            perror("accept");
35                            exit(EXIT_FAILURE);
36                        }
37                        //将新连接置于非阻塞模式
38                        setnonblocking(conn_sock);
39                        ev.events = EPOLLIN | EPOLLET;
40                        //注意这里的参数EPOLLIN|EPOLLET并没有设置对写socket的监听
41                        //如果有写操作的话,这个时候epoll是不会返回事件的
42                        //如果要对写操作也监听的话,应该是EPOLLIN|EPOLLOUT|EPOLLET
43                        //并且将新连接也加入EPOLL的监听队列
44                        ev.data.fd = conn_sock;
45                        if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
46                                    &ev) == -1) {
47                            //加入到epoll的监听队列里,这里用EPOLL_CTL_ADD
48                            //来加一个新的epoll事件,可以通过EPOLL_CTL_DEL减少
49                            //一个epoll事件,通过EPOLL_CTL_MOD来改变一个i额事件的监听方式
50                            perror("epoll_ctl: conn_sock");
51                            exit(EXIT_FAILURE);
52                        }
53                    } else {
54                        //如果不是主socket的事件的话,则代表这是一个用户的socket事件
55                        //则用来处理这个用户的socket的事情是,比如说read(fd, xxx)之类,或者一些其他的处理
56                        do_use_fd(events[n].data.fd);
57                    }
58                }
59            }    
epoll模型

 下面是个epoll的使用例子:

  1 #include <iostream>
  2 #include <sys/socket.h>
  3 #include <sys/epoll.h>
  4 #include <netinet/in.h>
  5 #include <arpa/inet.h>
  6 #include <fcntl.h>
  7 #include <unistd.h>
  8 #include <stdio.h>
  9 #include <errno.h>
 10 #include <stdlib.h>
 11 #include <strings.h>
 12 
 13 using namespace std;
 14 
 15 #define MAXLINE   5
 16 #define OPEN_MAX  100
 17 #define LISTENQ   20
 18 #define SERV_PORT 5000
 19 #define INFTIM    1000
 20 
 21 void setnonblocking(int sock)
 22 {
 23     int opts;
 24     opts = fcntl(sock, F_GETFL);
 25     if(opts < 0) {
 26         perror("fcntl(sock, GETFL)");
 27         exit(1);
 28     }
 29     opts = opts | O_NONBLOCK;
 30     if(fcntl(sock, F_SETFL, opts) < 0) {
 31         perror("fcntl(sock, SETFL, opts)");
 32         exit(1);
 33     }
 34 }
 35 
 36 int main()
 37 {
 38     int i, maxi, listenfd, connfd, sockfd, epfd, nfds;
 39     ssize_t n;
 40     char line[MAXLINE];
 41     socklen_t clilen;
 42 
 43     struct epoll_event ev, events[20];
 44     epfd = epoll_create(256);
 45     struct sockaddr_in clientaddr;
 46     struct sockaddr_in serveraddr;
 47     listenfd = socket(AF_INET, SOCK_STREAM, 0);
 48 
 49     setnonblocking(listenfd);
 50     ev.data.fd = listenfd;
 51     ev.events = EPOLLIN | EPOLLET;
 52     epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
 53     bzero(&serveraddr, sizeof(serveraddr));
 54     serveraddr.sin_family = AF_INET;
 55     char *local_addr = "192.168.1.63";
 56     inet_aton(local_addr, &(serveraddr.sin_addr));
 57     serveraddr.sin_port = htons(SERV_PORT);
 58     bind(listenfd, (sockaddr *)&serveraddr, sizeof(serveraddr));
 59     listen(listenfd, LISTENQ);
 60 
 61     maxi = 0;
 62     for( ; ; ) {
 63         nfds = epoll_wait(epfd, events, 20, 500);
 64         for(i=0;i<nfds;i++) {
 65             if(events[i].data.fd == listenfd) {
 66                 connfd = accept(listenfd, (sockaddr *)&clientaddr, &clilen);
 67                 if(connfd < 0) {
 68                     perror("connfd < 0");
 69                     exit(1);
 70                 }
 71                 setnonblocking(connfd);
 72                 char *str = inet_ntoa(clientaddr.sin_addr);
 73                 std::cout<<"connect from"<<str<<std::endl;
 74                 ev.data.fd = connfd;
 75                 ev.events = EPOLLIN | EPOLLET;
 76                 epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
 77             } else if(events[i].events & EPOLLIN) {
 78                 if((sockfd = events[i].data.fd) < 0) {
 79                     continue;
 80                 }
 81                 if((n = read(sockfd, line, MAXLINE)) < 0) {
 82                     if(errno == ECONNRESET) {
 83                         close(sockfd);
 84                         events[i].data.fd = -1;
 85                     } else {
 86                         std::cout<<"readline error"<<std::endl;
 87                     }
 88                 } else if(n == 0) {
 89                     close(sockfd);
 90                     events[i].data.fd = -1;
 91                 }
 92                 ev.data.fd = sockfd;
 93                 ev.events = EPOLLOUT | EPOLLET;
 94                 epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
 95             } else if(events[i].events & EPOLLOUT) {
 96                 sockfd = events[i].data.fd;
 97                 write(sockfd, line, n);
 98                 ev.data.fd = sockfd;
 99                 ev.events = EPOLLIN | EPOLLET;
100                 epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
101             }
102         }
103     }
104 }
epoll例子

 

转载于:https://www.cnblogs.com/ch122633/p/8457782.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/369620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

background使用

background-position 有两个参数&#xff0c;定义背景图片起始位置可选值有&#xff1a; center top left right bottom px % background-size 可以用 px % 设定其宽高 值 cover 完全覆盖背景区域 contain 适应背景区域 background-origin 背景图片可以放置于 content-bo…

java牛客排序算法题_《剑指offer》面试题28:字符串的排列(牛客网版本) java...

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。输入描述: 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。这里尤其需要注意2点&#xff1a;1.所有组…

前端之bootstrap模态框

简介&#xff1a;模态框&#xff08;Modal&#xff09;是覆盖在父窗体上的子窗体。通常&#xff0c;目的是显示来自一个单独的源的内容&#xff0c;可以在不离开父窗体的情况下有一些互动。子窗体可提供信息、交互等。 Modal简介Modal实现弹出表单Modal实现删除提示框其他用法…

js方式调用php_举例说明JS调用PHP和PHP调用JS的方法

举例说明JS调用PHP和PHP调用JS的方法在学习任何一门编程语言&#xff0c;我们都会听到调用这个词&#xff0c;那么&#xff0c;在javascript中是如何调用php的呢&#xff1f;在php中也可以调用js吗&#xff1f;下面就让我们一起来看看吧。1、JS方式调用PHP文件并取得PHP中的值举…

如何在Hexo中实现自适应响应式相册功能

用最清晰简洁的方法整合一个响应式相册效果 技术选型 由于我选用的主题使用了fancyBox作为图片弹出展示的框架&#xff0c;查看后表示很不错&#xff0c;能满足需要http://fancyapps.com/fancybox/3/图片加载可能会太慢&#xff0c;所以还需要一个图片延迟加载插件 Lazyload想使…

适用于MongoDB和Mongometer的SpiderMonkey至V8

通过10gen将MongoDB 2.3 / 2.4的默认JavaScript引擎从SpiderMonkey切换到V8&#xff0c;我想我将借此机会使用mongometer比较这些发行版的相对性能。 作为安全专家&#xff0c;我真的应该首先研究“ 其他身份验证功能” ……嘿。 我将记录比较过程中所采取的步骤&#xff08;包…

百度联盟广告如何理解按父容器宽度

创建百度联盟广告位的时候&#xff0c;选择按父容器宽度展示&#xff0c;但是在加入之后&#xff0c;查看代码发现广告的宽度为页面的宽度&#xff0c;并不是希望的父级的宽度&#xff0c; 如图在这里查看&#xff1a; 解析&#xff1a;百度联盟广告自动生成的div按父级的div宽…

php中文字转,PHP文字转图片功能原理与实现方法分析

本文实例讲述了PHP文字转图片功能。分享给大家供大家参考&#xff0c;具体如下&#xff1a;这项功能主要用于对邮箱地址、手机等可能被网络爬虫抓取的重要信息的处理。将文字转化为图片绝对是个好注意。验证码的基本生成原理也与此差不多&#xff0c;只是对再对文字转化为图片的…

Java 系列之spring学习--spring搭建(一)

一、新建maven项目 二、引入spring jar包 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0…

php简单分页,php简单实现分页查询的方法

这篇文章主要为大家详细介绍了php简单实现分页查询的方法&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下关于php,最近学了好多&#xff0c;老师跟我们说&#xff0c;现在学的都是php的核心部分&#xff0c;所以我比较注意了一下&#xff0c;也多练习…

django用户认证系统——登录4

用户已经能够在我们的网站注册了&#xff0c;注册就是为了登录&#xff0c;接下来我们为用户提供登录功能。和注册不同的是&#xff0c;Django 已经为我们写好了登录功能的全部代码&#xff0c;我们不必像之前处理注册流程那样费劲了。只需几分钟的简单配置&#xff0c;就可为用…

web前端黑客技术揭秘 6.漏洞挖掘

6.1  普通XSS漏洞自动化挖掘思路 6.1.1  URL上的玄机 6.1.2  HTML中的玄机 2.HTML标签之内 6.1.3  请求中的玄机 6.1.4  关于存储型XSS挖掘 6.2.1  HTML与JavaScript自解码机制 <input type"button" id"exec_btn" value"exec" on…

Webpack基础使用

目录 一.什么是Webpack 二.为什么要使用Webpack 三.Webpack的使用 1.下载yarn包管理器 2.Webpack的安装 3.Webpack的简单使用 4.效果 四.Webpack打包流程 一.什么是Webpack Webpack是一个静态模块打包工具 二.为什么要使用Webpack 在开发中&#xff0c;我们常常会遇到…

阿帕奇骆驼遇见Redis

键值商店的兰博基尼 Camel是最好的面包集成框架&#xff0c;在本文中&#xff0c;我将向您展示如何通过利用另一个出色的项目Redis使它更加强大。 Camel 2.11即将发布&#xff0c;具有许多新功能&#xff0c;错误修复和组件。 这些新组件中的几个是我创作的&#xff0c; red…

HTML 教程- (HTML5 标准)摘抄笔记

HTML 教程- (HTML5 标准) 教程网址&#xff1a;http://www.runoob.com/html/html-tutorial.html http://blog.csdn.net/ljfbest/article/details/6700148 HTML版本 从初期的网络诞生后&#xff0c;已经出现了许多HTML版本: 版本发布时间HTML1991HTML 1993HTML 2.01995HTML 3…

Java EE CDI ConversationScoped示例

在本教程中&#xff0c;我们将向您展示如何在Web应用程序中创建和使用ConversationScoped Bean。 在CDI中&#xff0c;bean是定义应用程序状态和/或逻辑的上下文对象的源。 如果容器可以根据CDI规范中定义的生命周期上下文模型来管理其实例的生命周期&#xff0c;则Java EE组件…

Git 中文教程

以下内容转载自&#xff1a;http://www.open-open.com/lib/view/open1328928294702.html Git是一个分布式的版本控制工具&#xff0c;本篇文章从介绍Git开始&#xff0c;重点 在于介绍Git的基本命令和使用技巧&#xff0c;让你尝试使用Git的同时&#xff0c;体验到原来一个版本…

php markdown的转化函数,markdown公式转为知乎格式

在知乎中写技术类文章&#xff0c;经常会用到markdown知乎文章可以导入markdown格式&#xff0c;但是不支持Latex公式。知乎大神提供了替代方案&#xff1a; https://zhuanlan.zhihu.com/p/69142198为实现自动化&#xff0c;用python将其简易实现&#xff0c;代码如下&#xff…

Java EE CDI Producer方法教程

这是CDI Producer方法的教程。 在CDI中&#xff0c;生产者方法生成一个可以注入的对象。 当我们要注入本身不是bean的对象&#xff0c;要注入的对象的具体类型在运行时可能有所不同&#xff0c;或者当对象需要一些bean构造函数不执行的自定义初始化时&#xff0c;可以使用生产者…

牛客网Java刷题知识点之方法覆盖(方法重写)和方法重载的区别

不多说&#xff0c;直接上干货&#xff01; https://www.nowcoder.com/ta/review-java/review?query&asctrue&order&page6 方法重写的原则&#xff1a; 重写方法的方法名称、参数列表必须与原方法的相同&#xff0c;返回类型可以相同也可以是原类型的子类型(从Jav…