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,一经查实,立即删除!

相关文章

为什么我不能关闭垃圾收集器?

首先让我们快速回顾一下我作为Java开发人员的职业生涯的早期。 我想消除正在进行的测试中的垃圾回收&#xff08;GC&#xff09;暂停。 瞧&#xff0c;当我发现无法完成时&#xff0c;我很生气。 那时&#xff0c;我将问题抛在了“设计错误”上&#xff0c;并继续前进。 对Jame…

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.所有组…

致第8年的自己

刚开始工作时&#xff0c;可能会用很多技术&#xff0c;知道很多技术就好像是很了不起的了。 但工作久了之后&#xff0c;如果还是只停留在知识的表面&#xff0c;技术只知个大概&#xff0c;那就显得太肤浅了。 别被人问倒&#xff0c;什么东西都能说出个一二&#xff0c;那才…

配置Ubuntu虚拟环境

配置Ubuntu虚拟环境 1.ubuntu默认root用户没有激活&#xff0c;激活root用户&#xff0c;就要为root用户创建密码$sudo passwd root2、修改主机名$vi /etc/hostname3、安装ssh服务$sudo apt-get install openssh-server//安装sshd服务$ sudo apt-get install openssh-server//开…

布局 — 样式重置

/* 清除默认内边距和外边距*/ body, dl, dd, h1, h2, h3, h4, h5, h6, p, form {margin: 0; } ol, ul {margin:0;padding:0; }/* 设置默认文字样式*/ html {font-size: calc((16 * 100vw) / 320);-webkit-text-size-adjust: none; } body, button, input, select, textarea {fo…

从Java执行可执行的命令行

在本文中&#xff0c;我们将介绍Java开发人员的常见需求。 从Java内部执行和管理外部流程。 由于这项任务很常见&#xff0c;因此我们着手寻找一个Java库来帮助我们完成它。 该库的要求是&#xff1a; 异步执行该过程。 能够中止流程执行。 等待流程完成的能力。 处理中的输…

java代码实现解压文件_Java压缩/解压文件的实现代码

用java压缩/解压文件&#xff1a;import java.io.*;import java.awt.*;import java.awt.event.*;import java.util.*;import java.util.zip.*;import javax.swing.*;//从压缩包中提取文件public class ZipExtractDemo extends JFrame{JFileChooser fileChooser; //文件选择器JT…

关于微信分享的一些心得之recommend.js(直接复制就行)

// import $ from jqueryimport Vue from vueexport default function (type,title,con,img,url,) { // 这里面的参数&#xff0c;你想怎么改就怎么改&#xff08;你自己也可以添加&#xff09;&#xff0c;类型&#xff0c;标题&#xff0c;内容&#xff0c;图片&#xff0c…

前端之bootstrap模态框

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

Python Excel操作——xlrd、xlwd

读取 1、导入模块 import xlrd 2、打开Excel文件读取数据 data xlrd.open_workbook(excel.xls) 3、获取一个工作表 1 table data.sheets()[0] #通过索引顺序获取 2 table data.sheet_by_index(0) #通过索引顺序获取 3 table data.sheet_by_name(uSheet1)#通过名…

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

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

Java大新闻不断涌现:Java SE 6和OpenJDK

我最近公布的最新的Java 8新闻 &#xff0c;总结了一些最近的事态发展中的Java 8 。 自从发布该文章不到一周&#xff0c;就出现了更多重要的Java新闻报道&#xff0c;我在本文中总结了其中的一些内容。 共同的主题包括不同的Java SE 6实现和OpenJDK 。 Java安全性问题影响Ora…

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

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

vue css动画

.toggle-cart-enter-active, .toggle-cart-leave-active { transition: all .3s ease-out; } .toggle-cart-enter, .toggle-cart-leave-active { transform: translateY(100%); }

luinx php木马,Linux Bash Shell 寻找PHP(网站)挂马,后门

一php后门木马常用的函数大致上可分为四种类型&#xff1a;1. 执行系统命令: system, passthru, shell_exec, exec, popen, proc_open2. 代码执行与加密: eval, assert, call_user_func,base64_decode, gzinflate, gzuncompress, gzdecode, str_rot133. 文件包含与生成: requir…

关于类型安全的思考

这两天一初学python的哥们频频吐槽C#这样赋值时对类型的检查,让问题变难变复杂了. 解释几次类型检查的好处,效果不明显. 我也反思了一下, 类型检查真的是额外的包袱么?答案 是忠言逆耳利于行。 你是君王&#xff0c;语言是臣子,在君王犯错的时候: 一个臣子在事后说“你让我干的…

适用于MongoDB和Mongometer的SpiderMonkey至V8

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

vue todolist

最近初学vue&#xff0c;做最简单的todolist <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>todolist</title><style type"text/css">#container{width: 700px;height: 100px;padding: 40px;margin…

python函数-函数进阶

python函数-函数进阶 一、命名空间和作用域 1.命名空间 内置命名空间 —— python解释器     就是python解释器一启动就可以使用的名字存储在内置命名空间中     内置的名字在启动解释器的时候被加载进内存里全局命名空间 —— 我们写的代码但不是函数中的代码 …