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. 自学linux——10.Linux的网络知识

    linux的网络知识 一.网络相关概述 1.网络的分类 局域网(LAN):在几百米到十几公里内办公楼群或校园内的计算机相互连接所构成的计算机网络 城域网(MAN):覆盖相距不远的几栋办公楼,也可以覆盖 ...

  2. 用 Java 实现常见的 8 种内部排序算法

    一.插入类排序 插入类排序就是在一个有序的序列中,插入一个新的关键字.从而达到新的有序序列.插入排序一般有直接插入排序.折半插入排序和希尔排序. 1. 插入排序 1.1 直接插入排序 /** * 直接 ...

  3. OpenStack虚拟网络与物理网络的衔接(flat方式)

    by 无若 这边以CentOS7+Liberty版本为例. 过去一段时间(Juno版本之前版本),OpenStack内的虚拟网络与真正的物理网络衔接主要使用openvswitch,其主要问题是在配置网 ...

  4. 深入理解jvm-2Edition-类文件结构

    概述: 规范而独立的类文件结构以及只与类文件关联的虚拟机为Java实现了平台无关性,甚至还带来了一些语言无关性. 只要将源代码编译为Class文件规定的格式,JVM就可以执行. JVM的指令描述能力比 ...

  5. 关于数字化工厂&智能工厂建设 IT 经验总结

    最近疫情闹得胆战心惊,前不久客户给我开了一个玩笑,当天我们同桌会议了一天,晚上客户回家之后就被隔离了,当他给我发这个消息的时候背都凉了一截,害怕之余在机场呆了一个晚上,捅乐鼻孔插了嗓子之后确认无事,后 ...

  6. c++ 跨平台线程同步对象那些事儿——基于 ace

    前言 ACE (Adaptive Communication Environment) 是早年间很火的一个 c++ 开源通讯框架,当时 c++ 的库比较少,以至于谈 c++ 网络通讯就绕不开 ACE, ...

  7. Windows内核开发-6-内核机制 Kernel Mechanisms

    Windows内核开发-6-内核机制 Kernel Mechanisms 一部分Windows的内核机制对于驱动开发很有帮助,还有一部分对于内核理解和调试也很有帮助. Interrupt Reques ...

  8. 题解—P2898 [USACO08JAN]Haybale Guessing G

    pre 首先注意一下翻译里面并没有提到的一点,也是让我没看懂样例的一点,就是这个长度为 \(n\) 的数组里面的数各不相同. 有很多人用并查集写的这道题,题解里面也有一些用线段树写的,不过我认为我的做 ...

  9. com.github.ulisesbocchio:jasypt-spring-boot-starter:2.0.0引用了sping cloud Finchley.M8版本,一直报错说不能从阿里云下载

    解决方法: 1.找到idea或者eclipase中maven插件引向得settings.xml文件 2.修改文件中<mirror/>标签(配置仓库镜像用得)中<mirrorOf/&g ...

  10. sentinel安装

    sentinel介绍 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性. Sentinel 具有以 ...