/**************************************************************************
>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;
}
测试结果:
相关推荐
IDEA 导入 jbolt项目(实验室非公开项目)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录准备一、准备数据库二、IDEA导入jbolt项目 准备 在实验室群文件中下载jbolt.zip和mysql.sql两个文件 将其解压到自己的目录下 一、准备数据库 打开Navicat新建一个jbolt数据库(字符集为utf8) 导入mysql.sql文件 数据库导入完毕 二、IDEA导入jbolt项目 点击打开一个项目 选择jbolt文件夹 以Maven形式打开 打开pom.xml 在里面添加jetty-server依赖
自己趟过epoll的坑
坑的背景 本人用epoll来实现多路复用,epoll触发模式有两种: ET(边缘模式)LT(水平模式) LT模式 是标准模式,意味着每次epoll_wait()返回后,事件处理后,如果之后还有数据,会不断触发,也就是说,一个套接字上一次完整的数据,epoll_wait()可能会返回多次,直到没有数据为止。 ET模式 也称高效模式,有数据过来后,epoll_wait()会
【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube
本教程基于群晖的NAS设备DS423+的docker功能进行搭建,DSM版为 7.2.1-69057 Update 5。MetaTube是一个媒体服务器插件,主要用于Emby和Jellyfin媒体服务器。它的主要功能是从互联网上抓取内容并响应 JSON 数据,然后通过预安装的 MetaTube 插件请求服务器并下载相应的元数据,以与 Jellyfin/Emby 服务器配合使用。使用 MetaTube 的步骤大致如下:部署后端:首先,需要部署一个名为 的后端 API 服务器来抓取内容。
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...
Augustus手动安装教程
本文记载了如何结合conda手动安装Augustus
保姆级教程:用PyTorch从零实现SDE扩散模型(附完整代码与MNIST实战)
本文提供了一份详细的PyTorch教程,指导读者从零开始实现SDE扩散模型,并附有完整的代码示例和MNIST数据集实战。通过解释随机微分方程(SDE)的核心概念、模型架构设计、训练流程实现以及采样生成过程,帮助开发者掌握扩散模型的构建与应用。
I/O 多路转接epoll
当ET底层缓冲区有数据后,ET只会通知用户进程一次,逼着用户一次要把缓冲区的数据读完,但是用户并不知道缓冲区的数据大小,只能进行循环读取recv,一旦底层缓冲区的数据被读完后,再调用recv如果是阻塞模式就被阻塞了,服务器就会被挂起。struct epoll_event结构中有两个成员,第一个成员events表示的是需要监视的事件,第二个成员data是一个联合体结构,一般选择使用该结构当中的fd,表示需要监听的文件描述符。网络协议栈或驱动层,当某个 fd 上有数据可读、可写或异常时,触发底层的。
python爬取《你好, 李焕英》豆瓣评论数据
# 导入工具包 import requests from bs4 import BeautifulSoup import time import pandas as pd import numpy as np # 请求头 headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'} # =
I/O多路转接——select,poll,epoll
本文介绍了几种不同的多路转接模型,详细谈了一下epoll的工作模式
使用MLP解决OCR问题(OpenCV)(下)
分类模型: 分类模型涉及的一个比较关键的问题就是输出的10维向量是如何与具体的类别挂钩的。实际上:10维向量的每一位都代表一类,在对于训练集的表达中,如果输入数据是0,则10维向量的第一位赋值为1,其余均为0。即0对应[1,0,0,0,0,0,0,0,0,0]。MLP模型训练完成后,就需要对用户输入的数据所属类别进行判定。这时得到的输出数据基本不可能是正好的所属类为1,其他位置为0
如何绘制电气绝缘图(GB9706.1-2007和GB9706.1-2020差异)
是用来描述要考虑设备的绝缘状况和它们的值 ,从而便于和相关部门交流和沟通,如权威机构和检测实验室等。本文为绝缘图的实例, 包括所有相关的绝缘路径以及介电强度,爬电距离和电气间隙的值。
【Linux网络】I/O多路转接技术 - epoll
本篇博文对【Linux网络】I/O多路转接技术 - epoll做了一个较为详细的介绍,不知道对你有没有帮助呢觉得博主写得还不错的三连支持下吧!会继续努力的~
VC中sqlite的使用
在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示
【Linux】I/O 多路转接:select & epoll 技术剖析
本文详细介绍了 Linux 下的 I/O 多路复用技术,包括 select、poll 和 epoll 的原理、优缺点及使用场景。select 和 poll 适用于少量连接,而 epoll 在处理大量并发连接时表现出色,文章通过示例代码展示了如何使用这些技术实现服务器程序,强调了根据实际需求选择合适的 I/O 模型的重要性。
假人有限元模型
假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用
VB摄像头监控
该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制
I/O多路转接之select、poll、epoll详解
select是一个系统调用,用来进行I/O多路转接select可以让程序同时监视多个文件描述符上的事件是否就绪当监视的多个文件描述符中有一个或多个事件就绪时,select才会成功返回并将对应的文件描述符就绪的事件告知调用者。
精雕软件(JDpaint) 5.5 绿色版
精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版
I/O多路转接 —— epoll
其中文件描述符0、1、2是默认打开的,分别对应的是标准输入、标准输出和标准错误,3号文件描述符对应的是服务器创建的epoll模型,4号文件描述符对应的是监听套接字,5号和6号文件描述符对应的分别是正在访问服务器的两个客户端。在epoll中,对于每一个事件都会有一个对应的epitem结构体,红黑树和就绪队列当中的节点分别是基于epitem结构中的rbn成员和rdllink成员的,epitem结构当中的成员ffd记录的是指定的文件描述符值,event成员记录的就是该文件描述符对应的事件。
[计算机网络]--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一般被忽略,返回值是一个文件描...
974



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



