1. epoll原理

原理性的知识不再另做说明,我在这里附上收藏整理的两篇经典文章:

select与epoll的本质关系。

select、poll、epoll之间的区别

2. epoll服务器端经典示例

2.1 逻辑框架

2.2 代码

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <pthread.h> #define true 1
#define false 0
#define MAX_EVENT_NUMBER 1024
#define BUFFER_SIZE 10 /*将文件描述符设置为非阻塞*/
int setnonblocking(int fd)
{
int old_option = fcntl(fd, F_GETFL);
int new_option = old_option | O_NONBLOCK;
fcntl(fd, F_SETFL, new_option);
return old_option;
} /*将文件描述符fd上的EPOLLIN注册到epollfd指示的epoll内核事件表中。 参数enable_et 指定是否对fd采用ET模式*/
void addfd(int epollfd, int fd, int enable_et)
{
struct epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN;
if(enable_et){
event.events |= EPOLLET;
}
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event );
setnonblocking(fd);
}
/*LT 模式的工作原理*/
void lt(struct epoll_event *events, int number, int epollfd, int listenfd)
{
char buf[BUFFER_SIZE];
int i = 0;
for(i= 0;i<number;i++){
int sockfd = events[i].data.fd;
if(sockfd == listenfd){
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr *)&client_address, &client_addrlength);
addfd(epollfd, connfd, false);
}else if(events[i].events & EPOLLIN){
/*只要socket读缓存中的还有未读的数据,此代码就能触发*/
printf("event trigger once\n");
memset(buf, 0, BUFFER_SIZE);
int ret = recv(sockfd, buf, BUFFER_SIZE-1, 0);
if(ret <= 0){
close(sockfd);
continue;
}
printf("get %d bytes of content: %s\n", ret, buf);
}else{
printf("Something else happen !!!\n");
}
}
} /*ET 模式的工作流程*/
void et(struct epoll_event* events, int number, int epollfd, int listenfd)
{
char buf[BUFFER_SIZE];
int i=0;
for(i =0; i<number; i++){
int sockfd = events[i].data.fd;
if(sockfd == listenfd){
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr* )&client_address, &client_addrlength); addfd(epollfd, connfd, true);/*对connfd开启ET模式*/
}else if(events[i].events & EPOLLIN){
/*这段代码不会被重复触发,所以我们循环读取数据,以确保把socket缓冲区的数据全部读取*/
printf("Event trigger once !!!\n");
while(1){
memset(buf, 0, BUFFER_SIZE);
int ret = recv(sockfd, buf, BUFFER_SIZE-1, 0);
if(ret < 0){
/*对于非阻塞IO,下面的事件成立标识数据已经全部读取完毕。此后,epoll就能再次触发sockfd上的sockfd的EPOLLIN事件,以驱动下一次读操作*/
if((errno == EAGAIN) || (errno == EWOULDBLOCK)){
printf("read later\n");
break;
}
close(sockfd);
break;
}else if(ret == 0){
close(sockfd);
}else{
printf("get %d bytes of content: %s\n", ret, buf);
} }
}else{
printf("something else happen\n");
} } } int main(int argc, char *argv[])
{
if(argc <= 2){
printf("Usage: %s ip_address port_number\n", argv[0]);
return 1;
}
const char *ip = argv[1];
int port = atoi(argv[2]); int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address)); address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port); int listenfd = socket(AF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0); ret = bind(listenfd, (struct sockaddr *)&address, sizeof(address));
assert(ret != -1); int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); ret = listen(listenfd, 5);
assert(ret != -1); struct epoll_event events[MAX_EVENT_NUMBER];
int epollfd = epoll_create(5);
assert(epollfd != -1); addfd(epollfd, listenfd, true);
while(1){
int ret = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
if(ret<0){
printf("epoll failure\n");
break;
}
//lt(events, ret, epollfd, listenfd);
et(events, ret, epollfd, listenfd);
}
close(listenfd);
return 0;
}

epoll经典代码示例的更多相关文章

  1. Python实现各种排序算法的代码示例总结

    Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示 ...

  2. 使用XStream注解实现Java对象与XML互相转换的代码示例

    本文记录一下使用xstream这个api的注解特性对Java对象与XML字符串相互转换的一些代码示例.    我们很多人都处理过XML文件,也有很多非常成熟的第三方开源软件.如:jdom.dom4j等 ...

  3. 高级渲染技巧和代码示例 GPU Pro 7

    下载代码示例 移动设备正呈现着像素越来越高,屏幕尺寸越来越小的发展趋势. 由于像素着色的能耗非常大,因此 DPI 的增加以及移动设备固有的功耗受限环境为降低像素着色成本带来了巨大的压力. MSAA 有 ...

  4. Java8-Function使用及Groovy闭包的代码示例

    导航 定位 概述 代码示例 Java-Function Groovy闭包 定位 本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋. 概述 在实际开发中,常常遇到使用模板模式的场 ...

  5. [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例

    懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...

  6. SELECT控件操作的JS代码示例

    SELECT控件操作的JS代码示例 1 检测是否有选中 if(objSelect.selectedIndex > -1) { //说明选中 } else { //说明没有选中 } 2.动态创建s ...

  7. 转:HIBERNATE一些_方法_@注解_代码示例---写的非常好

    HIBERNATE一些_方法_@注解_代码示例操作数据库7步骤 : 1 创建一个SessionFactory对象 2 创建Session对象 3 开启事务Transaction : hibernate ...

  8. C#与数据库访问技术总结(十五)之 DataAdapter对象代码示例

    DataAdapter对象代码示例 下面的代码将说明如何利用DataAdapter对象填充DataSet对象. private static string strConnect=" data ...

  9. C#与数据库访问技术总结(六)之Command对象创建SQl语句代码示例

    Command对象创建SQl语句代码示例 说明:前面介绍了 Command 对象的方法和一些属性,回顾一下 Command对象主要用来执行SQL语句.利用Command对象,可以查询数据和修改数据. ...

随机推荐

  1. 判断Windows系统是32位或64位并执行不同脚本命令

    判断Windows系统是32位或64位并执行不同脚本命令 https://www.autoahk.com/?p=16549&preview=true https://www.cnblogs.c ...

  2. 文件包含 & LFI-labs靶场

    文件包含漏洞学习 冲冲冲,好好学习 2020.1.30 认真对待自己做出的每一个决定 知识与实践 Q:什么是文件包含? A:简单一句话,为了更好地使用代码的重用性,引入了文件包含函数,可以通过文件包含 ...

  3. ElasticSearch入门检索

    前面简介说到 elsatic是通过RestFul API接口操作数据的,可以通过postman模拟接口请求测试一下 一._cat 1.GET /_cat/nodes:查看所有节点 2.GET /_ca ...

  4. 3个月零基础入门Python+数据分析,详细时间表+计划表分享

    ​大家好,我是白云. 今天想给大家分享的是三个月零基础入门数据分析学习计划.有小伙伴可能会说,英语好像有点不太好,要怎么办?所以今天我给大家分享的资源呢就是对国内的小伙伴很友好,还附赠大家一份三个月学 ...

  5. noip模拟35[第一次4题·裂了]

    noip模拟35 solutions 这是我第一次这么正式的考四个题,因为这四个题都出自同一个出题人,并不是拼盘拼出来的. 但是考得非常的不好,因为题非常难而且一直想睡觉.. 有好多我根本就不会的算法 ...

  6. [TensorFow2.0]-MNIST手写数字识别

    本人人工智能初学者,现在在学习TensorFlow2.0,对一些学习内容做一下笔记.笔记中,有些内容理解可能较为肤浅.有偏差等,各位在阅读时如有发现问题,请评论或者邮箱(右侧边栏有邮箱地址)提醒. 若 ...

  7. MyBatis学习04(注解开发)

    7.使用注解开发 7.1 面向接口编程 根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大家都遵守共同的标准 , 使得开发变得容易 , 规范性更好 在一个面 ...

  8. 备战秋招之十大排序——O(nlogn)级排序算法

    时间复杂度O(nlogn)级排序算法 五.希尔排序 首批将时间复杂度降到 O(n^2) 以下的算法之一.虽然原始的希尔排序最坏时间复杂度仍然是O(n^2),但经过优化的希尔排序可以达到 O(n^{1. ...

  9. python 日期、时间处理,各种日期时间格式/字符串之间的相互转换究竟是怎样的?

    模块函数说明 ''' date 日期对象,常用的属性有year,month,day time 时间对象,常用的属性有hour,minute,second,毫秒 datetime 日期时间对象,常用的属 ...

  10. C语言 使用char字符实现汉字处理

    系统:windows 64 编译器:gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 文本编辑器:notepa ...