epoll反应堆模型代码

libevent函数库核心思想

/***
epoll_loop.c
***/
#include<stdio.h>
#include<sys/epoll.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>#define MAX_EVENTS 2014
#define BUFLEN 4096
#define SERV_PORT 8080void recvdata(int fd,int events,void *arg);
void senddata(int fd,int events,void *arg);struct myevent_s
{int fd;int events;void *arg;void (*call_back)(int fd,int events,void *arg);int status;char buf[BUFLEN];int len;long last_active;
};int g_efd;
struct myevent_s g_events[MAX_EVENTS + 1];void eventset(struct myevent_s *ev,int fd,void (*call_back)(int,int,void*),void *arg)
{ev->fd = fd;ev->call_back = call_back;ev->events = 0;ev->arg = arg;ev->status = 0;ev->last_active = time(NULL);return;
}void eventadd(int efd,int events,struct myevent_s *ev)
{struct epoll_event epv = {0,{0}};int op;epv.data.ptr = ev;epv.events = ev->events = events;if(ev->status == 1){op = EPOLL_CTL_MOD; }else{op = EPOLL_CTL_ADD;ev->status = 1; }if(epoll_ctl(efd,op,ev->fd,&epv) < 0){printf("event add failed [fd=%d],evens[%d]\n",ev->fd,events) ;}else{printf("event add OK[fd=%d],op = %d,evens[%0X]\n",ev->fd,op,events) ;}return;
}void eventdel(int efd,struct myevent_s *ev)
{struct epoll_event epv = {0,{0}};if(ev->status != 1){return; }epv.data.ptr = ev;ev->status = 0;epoll_ctl(efd,EPOLL_CTL_DEL,ev->fd,&epv);return;
}void acceptconn(int lfd,int events,void *arg)
{struct sockaddr_in cin;socklen_t len = sizeof(cin);int cfd,i;if((cfd = accept(lfd,(struct sockaddr *)&cin,&len)) == -1){if(errno != EAGAIN && errno != EINTR) {}printf("%s : accept,%s \n",__func__,strerror(errno));return ;}do{for(i = 0; i < MAX_EVENTS; i++) {if(g_events[i].status == 0) {break; }}if(i == MAX_EVENTS){printf("%s: max connect limit[%d]\n]",__func__,MAX_EVENTS) ;return;}int flag = 0;if((flag = fcntl(cfd,F_SETFL,O_NONBLOCK)) < 0){printf("%s : accept,%s \n",__func__,strerror(errno));break;}eventset(&g_events[i],cfd,recvdata,&g_events[i]);eventadd(g_efd,EPOLLIN,&g_events[i]);}while(0);printf("new connect [%s:%d][time:%ld],pos[%d]\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),g_events[i].last_active,i);return;
}void recvdata(int fd,int events,void *arg)
{struct myevent_s *ev = (struct myevent_s *)arg;int len;len = recv(fd,ev->buf,sizeof(ev->buf),0);eventdel(g_efd,ev);if(len > 0){ev->len = len;ev->buf[len]  = 0;printf("C[%d]:%s\n",fd,ev->buf);eventset(ev,fd,senddata,ev);eventadd(g_efd,EPOLLOUT,ev);}else if(len == 0){close(ev->fd) ;printf("[fd = %d] pos[%ld],close\n",fd,ev-g_events);}else{close(ev->fd) ;printf("recv[fd=%d] error[%d]:%s\n",fd,errno,strerror(errno));}return;
}void senddata(int fd,int events,void *arg)
{struct myevent_s *ev = (struct myevent_s *)arg;int len;len = send(fd,ev->buf,ev->len,0);if(len > 0){printf("send[fd=%d],[%d]%s\n",fd,len,ev->buf) ;eventdel(g_efd,ev);eventset(ev,fd,recvdata,ev);eventadd(g_efd,EPOLLIN,ev);}else{close(ev->fd) ;eventdel(g_efd,ev);printf("send[fd=%d] error %s\n",fd,strerror(errno));}return;
}void initlistensocket(int efd,short port)
{int lfd = socket(AF_INET,SOCK_STREAM,0);fcntl(lfd,F_SETFL,O_NONBLOCK);eventset(&g_events[MAX_EVENTS],lfd,acceptconn,&g_events[MAX_EVENTS]);eventadd(efd,EPOLLIN,&g_events[MAX_EVENTS]);struct sockaddr_in sin;memset(&sin,0,sizeof(sin));sin.sin_addr.s_addr = INADDR_ANY;sin.sin_family = AF_INET;sin.sin_port = htons(port);bind(lfd,(struct sockaddr*)&sin,sizeof(sin));listen(lfd,20);return ;
}int main(int argc, char *argv[])
{unsigned short port = SERV_PORT;if(argc == 2){port = atoi(argv[1]) ;}g_efd = epoll_create(MAX_EVENTS+1);if(g_efd <= 0){printf("Create efd in %s error %s\n",__func__,strerror(errno)) ;}initlistensocket(g_efd,port);struct epoll_event events[MAX_EVENTS+1];printf("server running:port[%d]\n",port);int checkpos = 0,i;while(1){long now = time(NULL) ;for(i = 0 ; i < 100; i++,checkpos++){if(checkpos == MAX_EVENTS) checkpos = 0;if(g_events[checkpos].status != 1){continue; }long duration = now - g_events[checkpos].last_active;if(duration >= 60){close(g_events[checkpos].fd) ;printf("[fd=%d] timeout\n",g_events[checkpos].fd);eventdel(g_efd,&g_events[checkpos]);}}int nfd = epoll_wait(g_efd,events,MAX_EVENTS+1,1000);if(nfd < 0){printf("epoll_wait error, exit\n") ;break;}for(i = 0; i < nfd; i++){struct myevent_s *ev = (struct myevent_s *)events[i].data.ptr;if((events[i].events & EPOLLIN) && (ev->events & EPOLLIN)){ev->call_back(ev->fd,events[i].events,ev->arg) ;}if((events[i].events & EPOLLOUT) && (ev->events & EPOLLOUT)){ev->call_back(ev->fd,events[i].events,ev->arg);}}}return 0;
}

 

转载于:https://www.cnblogs.com/wanghao-boke/p/11443231.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384838.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UDP广播

广播是在局域网之间的一对多的通信方式&#xff0c;使用的udp协议 /*** client.c ***/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h>#define SERVER_PORT 8000 #define MAXLINE…

UDP组播

多播(组播) 组播组可以是永久的也可以是临时的。组播组地址中&#xff0c;有一部分由官方分配的&#xff0c;称为永久组播组。永久组播组保持不变的是它的ip地址&#xff0c;组中的成员构成可以发生变化。永久组播组中成员的数量都可以是任意的&#xff0c;甚至可以为零。那些没…

Python3数据结构

列表&#xff1a; Python列表是可变的&#xff0c;这是它区别于字符串数组和元组的最重要的特点。列表可以修改&#xff0c;而字符串和元组不能。 以下是Python中列表的描述方法&#xff1a; 方法 描述 list.append(x) 将元素添加到列表结尾 list.extend(L) 通过添加指定列…

sed、awk工具

ed sed意为流编辑器&#xff08;Stream Editor&#xff09;&#xff0c;在Shell脚本和Makefile中作为过滤器使用非常普遍&#xff0c;也就是把前一个程序的输出引入sed的输入&#xff0c;经过一系列编辑命令转换为另一种格式输出。sed和vi都源于早期UNIX的ed工具&#xff0c;所…

C语言正则表达式

POSIX规定了正则表达式的C语言库函数&#xff0c;详见regex(3)。我们已经学习了很多C语言库函数的用法&#xff0c;读者应该具备自己看懂man手册的能力了。本章介绍了正则表达式在grep、sed、awk中的用法&#xff0c;学习要能够举一反三&#xff0c;请读者根据regex(3)自己总结…

makefile通用版本

实际当中程序文件比较大&#xff0c;这时候对文件进行分类&#xff0c;分为头文件、源文件、目标文件、可执行文件。也就是说通常将文件按照文件类型放在不同的目录当中&#xff0c;这个时候的Makefile需要统一管理这些文件&#xff0c;将生产的目标文件放在目标目录下&#xf…

Python3OS文件/方法

Python3OS文件/方法 os模块提供了非常丰富的方法用来处理文件和目录。 方法 描述 os.access(path,mode) 检验权限模式 os.chdir(path) 改变当前工作目录 os.chflags(path,flags) 设置路径的标记为数字标记 os.chmod(path,mode) 更改权限 os.chown(path,uid,gid) 更改…

Python3文件

open()方法 Python open()方法永于打开一个文件&#xff0c;并返回文件对象&#xff0c;并对文件进行处理过程中都需要用到这个方法&#xff0c;如果该文件无法被打开&#xff0c;则抛出OSError 注意&#xff1a;使用open()方法一定要保证关闭文件对象&#xff0c;即调用close(…

Python3输入输出

Python两种输出值的方式&#xff0c;表达式语句和print()函数。 第三种方式是使用文件对象的write()方法&#xff0c;标准输出文件可以用sys.stdout的引用。 如果你希望输出的形式更加多样&#xff0c;可以使用str.fomat()函数来格式化输出值。 如果你希望将输出的值转化成字符…

动态库加载顺序

1.编译目标代码时指定的动态库搜索路径&#xff1b; 2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径&#xff1b; 3.配置文件/etc/ld.so.conf中指定的动态库搜索路径&#xff1b; 4.默认的动态库搜索路径/lib&#xff1b; 5.默认的动态库搜索路径/usr/lib。 转载于:https://ww…

Python3正则表达式

正则表达式是一个特殊的字符序列&#xff0c;他能帮助你方便的检查一个字符串是否与某种模式匹配。re.match函数 re.match尝试从字符串的起始位置匹配一个模式&#xff0c;如果不是起始位置匹配成功的话&#xff0c;match()就返回一个none。 函数语法&#xff1a; re.match(pat…

C/C++输入

fgets(str,n,stdin) 从键盘输入一行&#xff0c;替代gets()。读取到n-1字节时或换行符时终止&#xff0c;如果是文件的话&#xff0c;读到文件结尾也会停止 getline(cin,str) str的类型必须是string类&#xff0c;它是C特定的字符串类&#xff0c;区别于C的char *数据类型。 ci…

strlen和sizeof的区别

C语言中没有字符串&#xff0c;用的是字符数组来模拟字符串。 C风格的字符串时字符数组然后在末尾加0表示结尾。 在C语言中有strlen和sizeof两个函数求字符数组的长度函数&#xff0c;他们俩的区别就是是否把最后的结束标志也加上去。 strlen是不加的&#xff0c;他表示字符串的…

shell编程练习题

求2个数之和计算1-100的和将一目录下所有的文件的扩展名改为bak编译当前目录下的所有.c文件&#xff1a;打印root可以使用可执行文件数&#xff0c;处理结果: roots bins: 2306打印当前sshd的端口和进程id&#xff0c;处理结果: sshd Port&&pid: 22 5412输出本机创建20…

shell编程题(一)

求2个数之和 #!/bin/bashfunction add {if(( $# < 2 )); thenecho "The arg int correct"elsesum$(($1$2))echo $sumfi }add 1 add 1 2 运行结果&#xff1a; exbotubuntu:~/shareWin/linux/shell$ ./sum.sh 1 2The arg int correct3 $#&#xff1a;相当于C语言…

vimset

vim ~./vimrc set nocompatible "去掉有关vi一致性模式&#xff0c;避免以前版本的bug和局限 set nu! "显示行号 set guifontLuxi/ Mono/ 9 " 设置字体&#xff0c;字体名称和字号 filetype on …

shell编程题(二)

计算1-100之和 #!/bin/bashsum0 for i in seq 1 100;do #符号不是单引号 是 1左边的符号sum$[$i $sum ] done echo $sum #!/bin/bashi0 n1              #定义循环变量 while [ $n -lt 101 ];do  #循环变量小于101 i$(( $i $n))        #累加 n$(( …

vim命令大全

1. vim模式 正常模式&#xff08;按Esc或Ctrl[进入&#xff09; 左下角显示文件名或为空 插入模式&#xff08;按i进入&#xff09; 左下角显示--INSERT-- 可视模式&#xff08;按v进入&#xff09; 左下角显示--VISUAL-- 替换模式&#xff08;按r或R开始&#xff09; 左下角显…

signal()函数

函数原型 void (*signal(int sig,void(*func)(int)))(int); 指定使用sig指定的信号编号处理信号的方法。参数func指定程序可以处理信号的三种方式之一&#xff1a; l 默认处理(SIG_DFL)&#xff1a; 信号由该特定信号的默认动作处理l 忽略信号&#xff08;SIG_IGN&a…

setitimer()函数

定时器时间函数 struct itimerval&#xff1a;struct itimerval *new_value&#xff0c;其定义如下&#xff1a;struct itimerval {struct timeval it_interval; /*next value*/struct timeval it_value; /*current value*/};struct timeval {long tv_sec; /*seconds*/lonng t…