/**************************************************************************
>file name:my_epoll.c
>author:Comedly
>create time:2016-8-9
**************************************************************************/
#include<stdio.h>
#include<sys/epoll.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>
#include<unistd.h>
//static void my_read(int epfd,int fd,char *buf,int len)
//{
// int rs = 1;
// while(rs)
// {
// ssize_t size = recv(fd,buf,len,0);
// if(size < 0)
// {
// if(errno = EAGAIN)
// {
// break;
// }
// else
// {
// perror("recv");
// return 9;
// }
// }
// else if(size == 0)
// {
// //表示对端的sock已经正常关闭
// printf("client close....\n");
// struct epoll_event ev;
// epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
// close(fd);
// break;
// }
// else
// {
// buf[size - 1] = '\0';
// printf("client # %s\n",buf);
// if(size == len)
// {
// rs = 1;
// }
// else
// {
// rs = 0;
// }
// }
// }
//}
//static void my_write(int fd,char *buf,int len)
//{
// int ws = 1;
// while(ws)
// {
// ssize_t size = send(fd,buf,len,0);
// if(size < 0)
// {
// //缓冲区已满,延时重试
// if(errno == EAGAIN)
// {
// usleep(1000);
// continue;
// }
// if(errno == EINTR)
// {
// return -1;
// }
// }
// if(size == len)
// {
// continue;
// }
// len -= size;
// buf += size;
// }
//}
ssize_t my_read(int fd,char buf[])
{
int ret = 0;
int total = 0;
while((ret = read(fd,buf+total,sizeof(buf)-total)) && errno != EAGAIN)
{
total +=ret;
}
buf[total] = '\0';
return total;
}
static void set_no_block(int fd)
{
//先得到之前的状态,在之前的状态上加入新状态,将其设置为非阻塞。
int before = fcntl(fd,F_GETFL);
fcntl(fd,F_SETFL,before|O_NONBLOCK);
}
static int startup(const char *ip,int port)
{
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0 )
{
perror("socket");
return 2;
}
int opt = 1;
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr = inet_addr(ip);
if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
{
perror("bind");
return 3;
}
if(listen(sock,5) < 0)
{
perror("listen");
return 4;
}
return sock;
}
static void usage(const char* proc)
{
printf("%s [ip][port]\n",proc);
}
int main(int argc,char* argv[])
{
if(argc != 3)
{
usage(argv[0]);
return 1;
}
int listen_sock = startup(argv[1],atoi(argv[2]));
int epfd = epoll_create(128);
if(epfd < 0)
{
perror("epoll_create");
return 5;
}
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,listen_sock,&ev) < 0)
{
perror("epoll_ctl");
return 6;
}
struct epoll_event evs[128];
int len = sizeof(evs)/sizeof(evs[0]);
int ready = 0;
int timeout = -1;
while(1)
{
switch(ready = epoll_wait(epfd,evs,len,timeout))
{
case 0:
printf("timeout..\n");
break;
case -1:
printf("epoll_wait");
break;
default:
{
int i = 0;
for(;i < ready;i++)
{
int fd = evs[i].data.fd;
if(i == 0 && fd == listen_sock && evs[i].events&EPOLLIN)
{
struct sockaddr_in peer;
socklen_t len = sizeof(peer);
int new_sock = accept(listen_sock,(struct sockaddr*)&peer,&len);
if(new_sock < 0)
{
perror("accept");
return 8;
}
else
{
//在epoll_wait之后改变其文件状态,为非阻塞,ET工作
set_no_block(new_sock);
printf("get new client:ip %s:port %d\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
ev.events = EPOLLIN|EPOLLET;
ev.data.fd=new_sock;
if(epoll_ctl(epfd,EPOLL_CTL_ADD,new_sock,&ev)<0)
{
perror("epoll_ctl");
return 9;
}
}
}
else
{
//read
if(evs[i].events&EPOLLIN)
{
char buf[1024];
ssize_t _s = my_read(fd,buf);
//ssize_t _s = recv(fd,buf,sizeof(buf)-1,0);
if(_s > 0)
{
buf[_s] = '\0';
printf("client # %s\n",buf);
ev.data.fd = fd;
ev.events = EPOLLOUT |EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&ev);
}
else if(_s == 0)
{
//client close
printf("client close...\n");
epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
close(fd);
}
else
{
perror("my_read");
return 10;
}
}
else if(evs[i].events&EPOLLOUT)
{
char *msg = "HTTP/1.1 200 ok\r\n\r\n<html><h1>hello Comedly</h1></html>\r\n";
//send(fd,msg,sizeof(msg)-1);
//send(fd,msg,strlen(msg),0);
write(fd,msg,strlen(msg));
epoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);
close(fd);
}
else
{
continue;
}
}
}
}
break;
}
}
return 0;
}
测试结果:
相关推荐
汇总药用数据库(Pubchem,bingdingDB,Chembl,ExcapeDB)数据
记载一下如何汇总4大数据库的数据
自己趟过epoll的坑
坑的背景 本人用epoll来实现多路复用,epoll触发模式有两种: ET(边缘模式)LT(水平模式) LT模式 是标准模式,意味着每次epoll_wait()返回后,事件处理后,如果之后还有数据,会不断触发,也就是说,一个套接字上一次完整的数据,epoll_wait()可能会返回多次,直到没有数据为止。 ET模式 也称高效模式,有数据过来后,epoll_wait()会
Flink项目基础配置指南
在大数据处理领域,Apache Flink凭借强大的实时流处理和批处理能力,成为众多开发者的首选工具。在日常工作中,开发Flink Jar任务是常见需求,但每次都需重复配置日志、梳理pom依赖、设置打包插件等,流程繁琐且易出错。为提升开发效率,减少重复劳动,将这些基础配置进行整理归纳十分必要。本文将围绕Flink项目的本地日志配置、pom依赖及插件配置展开详细介绍,为开发者提供一套可直接复用的基础配置方案,助力Flink项目高效开发。在Flink项目中,日志是了解任务运行状态、排查问题的重要依据。本地日志配
poll与epoll
poll poll函数接口 #include <poll.h> int poll(struct pollfd *fds,nfds_t nfds,int timeout); //参数1 结构体指针(结构体数组的首地址) //参数2 数组长度 //参数3 poll函数的超时时间(同select) //返回值小于0,出错,等于0,poll函数等待超时 //大于0,表示pol...
压电阀控制器设计-总章
本文章用于回顾记录本人制作压电阀控制器的关键技术,本人所制作压电阀控制器已经上市得到应用,特在此对一些关键技术进行回顾记录,欢迎从事压电控制及压电阀相关人员一起讨论
Oracle EBS订单的流程(Order->AR)
基本流程创建订单路径:Order Management > Orders,Returns > Sales Orders填写订单头信息,客户,订单类型,销售人员填写订单体信息,输入物料,数量...然后Book Order,订单Book之后,你会发现订单头的Status的状态变成了“Booked”,订单行的状态为"Awaiting Shipping",记录下来你的订单号,后边的每一步都需要这个订单号。
I/O 多路转接epoll
当ET底层缓冲区有数据后,ET只会通知用户进程一次,逼着用户一次要把缓冲区的数据读完,但是用户并不知道缓冲区的数据大小,只能进行循环读取recv,一旦底层缓冲区的数据被读完后,再调用recv如果是阻塞模式就被阻塞了,服务器就会被挂起。struct epoll_event结构中有两个成员,第一个成员events表示的是需要监视的事件,第二个成员data是一个联合体结构,一般选择使用该结构当中的fd,表示需要监听的文件描述符。网络协议栈或驱动层,当某个 fd 上有数据可读、可写或异常时,触发底层的。
微信小程序 实现拼图功能
微信小程序 实现碎片拼图
I/O多路转接——select,poll,epoll
本文介绍了几种不同的多路转接模型,详细谈了一下epoll的工作模式
advanced installer 打包Flutter的Windows程序安装包(基本打包、开机自启、定时自动检测升级、包含卸载程序)
advanced installer 打包Flutter的Windows程序安装包(基本打包、开机自启、定时自动检测升级、包含卸载程序)
注意力机制详解
注意力机制详解Attention机制由来Attention定义Encoder-Decoder框架存在问题:Attenion机制的引入Attention机制的类别Hard AttentionSoft AttentionGlobal AttentionLocal AttentionSelf AttentionMulti-head Attention附录—Transformer全局视角Tensor视角Encoder部分Self-AttentionSelf-Attention向量计算Self-Attention的矩
【Linux网络】I/O多路转接技术 - epoll
本篇博文对【Linux网络】I/O多路转接技术 - epoll做了一个较为详细的介绍,不知道对你有没有帮助呢觉得博主写得还不错的三连支持下吧!会继续努力的~
PCIe ATS介绍
主机侧使用IOMMU完成设备地址到物理memory地址的转换,以及设备访问权限的检查。但如果所有PCIe设备都在进行DMA操作,则TA(Translation Agent)和ATPT(Address Translation and Protection Table)则会成为瓶颈,从而影响系统的latency。
【Linux】I/O 多路转接:select & epoll 技术剖析
本文详细介绍了 Linux 下的 I/O 多路复用技术,包括 select、poll 和 epoll 的原理、优缺点及使用场景。select 和 poll 适用于少量连接,而 epoll 在处理大量并发连接时表现出色,文章通过示例代码展示了如何使用这些技术实现服务器程序,强调了根据实际需求选择合适的 I/O 模型的重要性。
最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版
Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。
jdk-8u144-linux-x64.tar.gz.
该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包
I/O多路转接之select、poll、epoll详解
select是一个系统调用,用来进行I/O多路转接select可以让程序同时监视多个文件描述符上的事件是否就绪当监视的多个文件描述符中有一个或多个事件就绪时,select才会成功返回并将对应的文件描述符就绪的事件告知调用者。
jre9下载 jdk9
(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】
I/O多路转接 —— epoll
其中文件描述符0、1、2是默认打开的,分别对应的是标准输入、标准输出和标准错误,3号文件描述符对应的是服务器创建的epoll模型,4号文件描述符对应的是监听套接字,5号和6号文件描述符对应的分别是正在访问服务器的两个客户端。在epoll中,对于每一个事件都会有一个对应的epitem结构体,红黑树和就绪队列当中的节点分别是基于epitem结构中的rbn成员和rdllink成员的,epitem结构当中的成员ffd记录的是指定的文件描述符值,event成员记录的就是该文件描述符对应的事件。
OV9734 DATASHEET,完整规格书
OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等
[计算机网络]--I/O多路转接之poll和epoll
poll函数的相关接口,poll函数是如何实现多路转接的,epoll函数的学习,epoll函数的工作原理,poll函数和epoll函数服务器的实现。
【探索Linux】P.49(高级IO —— I/O多路转接之epoll )
本文全面介绍了epoll技术,包括其基本概念、相关系统调用(epoll_create、epoll_ctl、epoll_event结构体、epoll_wait)、工作原理(工作流程、事件触发模式)、优势以及使用示例。
I/O多路转接——select、poll、epoll
epoll有三个相关的系统调用,分别是epoll_create、epoll_ctl和epoll_wait。
I/O多路转接之select/poll/epoll
虽然当前的select服务器是一个单进程的服务器,但它却可以同时为多个客户端提供服务,根本原因就是因为select函数调用后会告知select服务器是哪个客户端对应的连接事件就绪了,此时select服务器就可以读取对应客户端发来的数据,读取完后又会调用select函数等待某个客户端连接的读事件就绪。此时如果select监视的文件描述符上有事件就绪,那么select函数的返回值就是大于0的,如果select监视的文件描述符上没有事件就绪,那么select的返回值就是等于0的。
Linux网络编程——I/O多路转接(2)之 poll、epoll
上篇文章中我们提到了I/O多路转接的select接口select的fd存在着上限每次调用都需要重新设置关心的fd针对select接口中存在的问题,本章中我们再来介绍其他的多路转接的接口——poll接口和epoll接口。
详解I/O多路转接模型:select & poll & epoll
文章技术分享思路:从select模型开始,先了解select模型的理论基础,然后编写简单的基于select的tcp服务器,接着分析出select的特点和缺点。引出poll模型,了解了poll模型的基础理论,编写简单的基于poll的tcp服务器。接着引出重要的epoll模型,了解epoll模型的理论以及原理,编写简单的基于epoll的tcp服务器,总结select、poll和epoll的区别,ET模式下epoll高效的原因。
揭秘epoll:高效I/O多路转接核心机制
I/O 多路转接是一种高效处理多个文件描述符(如套接字)的技术,允许单个线程或进程同时监视多个文件描述符的状态变化。epoll 是 Linux 提供的一种 I/O 多路转接机制,相比 select 和 poll,epoll 在大规模并发连接时性能更高,因为它避免了线性扫描所有文件描述符的开销。epoll 采用事件驱动模型,仅关注活跃的文件描述符,避免了 select/poll 的轮询开销。
I/O多路转接之select、poll、epoll
select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
I/O 多路转接之epoll
数据结构分离:红黑树用于快速增删改查监控集,就绪链表用于高效返回就绪事件。事件驱动回调:通过将回调函数注册到文件描述符的等待队列,实现“通知-唤醒”机制,避免无效轮询。灵活的触发模式:水平触发简化编程,边缘触发进一步提升性能,适应不同场景。正是这些设计,使得 epoll 能够轻松应对成千上万的并发连接,成为 Linux 下高性能网络编程的事实标准。
I/O多路转接之【epoll】
epoll 在Linux中,还提供了第三种I/O多路转接的方式,那就是epoll,它几乎具备了select和poll的全部优点,是公认的Linux2.6下的最好的多路I/O就绪通知方法。 先来看一下接口,再根据参数解释epoll的工作原理。epoll将多路转接拆分为三个步骤。 第一步:创建一个epoll语柄 这个函数用来创建一个epoll语柄,其中size一般被忽略,返回值是一个文件描...
3394



被折叠的 条评论
为什么被折叠?



