首页 » 网站建设 » phplibevent管道技巧_linux详解libevent收集库框架的搭建

phplibevent管道技巧_linux详解libevent收集库框架的搭建

访客 2024-12-09 0

扫一扫用手机浏览

文章目录 [+]

vim打开hello-world.c文件查看示例代码

创造监听端口号为:9995好,接下来我们开始libevent的奇妙之旅,利用xshell启动两个本地连接,

phplibevent管道技巧_linux详解libevent收集库框架的搭建

做事端:在上述路径实行 ./hello-world客户端:采取nc进行访问 nc 127.0.0.1 9995 9995为上述代码中指定的端口号

每有客户端注册时 server端将打印 flushed answer,同时,client端打印Hello, World!

phplibevent管道技巧_linux详解libevent收集库框架的搭建
(图片来自网络侵删)

须要C/C++ Linux做事器架构师学习资料私信“资料”(资料包括C/C++,Linux,golang技能,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

框架学习-- event_base 重中之重

源码中有这样一句话:The event_base lies at the center of Libevent; every application will have one.

夸年夜的理解为:libevent的天下中,event_base作为万物起源

利用 libevent 函数之前须要分配一个或者多个 event_base 构造体。
每个event_base构造体持有一个事宜凑集,可以检测以 确定哪个事宜是激活的。
(相称于epoll红黑树的树根)

从思想上出发

我们可以把libevent项目想象为造火箭的过程,我们都只是螺丝工,那么造火箭须要做什么?

1. 拿出火箭壳(创建框架)2. 造螺丝 (创建事宜)3. 拧螺丝 (添加事宜)4. 造火箭(事宜循环)

一:取出火箭壳 —>event_base()创建与开释

我们开始第一步:创建一个event_base

// 创建event_basestruct event_base event_base_new(void)

当然,作为一个精良的c措辞程序员(咳,我还是个菜),要在创建的同时考虑资源开释的问题,在程序的末了我们须要 event_base_free 进行开释(但我们不得不提前考虑)

// 开释event_base_freeevent_base_free(struct event_base base);12

二:造螺丝 —>event_new()创建与开释

注:创建事宜:(只针对不带缓冲区event事宜进行讲解)

// 创建新事宜struct event event_new(struct event_base base, evutil_socket_t fd, - // 文件描述符 - int 底层是对epollin与epollout的封装short what, event_callback_fn cb, // 事宜的处理回调函数void arg //回调函数传参); // 事宜的处理回调函数typedef void (event_callback_fn)(evutil_socket_t, short, void ); //short what#define EV_TIMEOUT 0x01 // 已淘汰(忽略)#define EV_READ 0x02#define EV_WRITE 0x04#define EV_SIGNAL 0x08 //libevent封装了旗子暗记干系的操作 SIGNAL#define EV_PERSIST 0x10 // 持续触发#define EV_ET 0x20 // 边沿模式

在程序的末了我们须要 event_free 进行开释(但我们不得不提前考虑)

// 创建event_freevoid event_free(struct event event);

调用event_new()函数之后, 新事宜处于已初始化和非未决状态 (翻译:螺丝造好了,还没拧到火箭时的状态)

三:拧螺丝 —>event_add()干系函数

创建事宜之后,在将其添加到 event_base 之前实际上是不能对其做任何操作的。
利用event_add()将事宜添加到event_base。
(将螺丝拧上去)非未决事宜 -> 未决事宜.

// event_addint event_add(struct event ev, const struct timeval tv);

函数调用成功返回0, 失落败返回-1

设置非未决(作为理解实际中少用)未决事宜 -> 非未决事宜.

//对已经初始化的事宜调用 event_del()将使其成为非未决和非激活的。
如果事宜不是未决的或者激活的,调用将没有效果。
int event_del(struct event ev); //成功时函数返回 0,失落败时返回-1。

有关于未决态和非未决态的理解:

1. 非未决: 没有资格被处理

2. 未决: 有资格被处理但是还没有处理

四:一节一节造火箭 —>event_base_dispatch()干系函数

末了,我们只需将添加 事宜循环利用event_base_dispatch()函数

// event_base_dispatch(简化版event_base_loop())int event_base_dispatch(struct event_base base);//等同于没有设置标志的 event_base_loop ( )//将一贯运行,直到没有已经注册的事宜了,或者调用 了event_base_loopbreak()或者 event_base_loopexit()为止

关于event_base_loop()函数

// event_base_loop()int event_base_loop(struct event_base base, int flags);//正常退出返回0, 失落败返回-1//flages#define EVLOOP_ONCE 0x01//事宜只会被触发一次//事宜没有被触发, 壅塞等#define EVLOOP_NONBLOCK 0x02//非壅塞 等办法去干变乱检测//不关心事宜是否被触发了#define EVLOOP_NO_EXIT_ON_EMPTY 0x04//没有事宜的时候, 也不退出轮询检测

关于退失事宜循环函数event_base_loopexit()与event_base_loopbreak():

实行当前退却撤退出 event_base_loopexit()

//如果 event_base 当前正在实行激活事宜的回调 ,它将在实行完当前正在处理的事宜后立即退出 int event_base_loopexit(struct event_base base,const struct timeval tv);//参数struct timeval tvstruct timeval { long tv_sec; long tv_usec; };

立即退出循环 event_base_loopbreak()

//让event_base 立即退出循环 int event_base_loopbreak(struct event_base base); //返回值: 成功 0, 失落败 -1

Demo

末了举个栗子:注:用不带缓冲区操作时的写法:采取fifo通讯的办法

//write_fifo.c#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <fcntl.h>#include <event2/event.h>// 回调函数void write_cb(evutil_socket_t fd, short what, void arg){ // write管道 char buf[1024] = {0}; static int num = 666; sprintf(buf, "hello, world == %d\n", num); write(fd, buf, strlen(buf)+1);}int main(int argc, const char argv[]){ // open file int fd = open("myfifo", O_WRONLY | O_NONBLOCK); if(fd == -1) { perror("open error"); exit(1); } // 写管道 struct event_base base = NULL; base = event_base_new(); // 创建事宜 struct event ev = NULL; // 检测的写缓冲区是否有空间写 ev = event_new(base, fd, EV_WRITE , write_cb, NULL); // 添加事宜 event_add(ev, NULL); // 事宜循环 event_base_dispatch(base); // 开释资源 event_free(ev); event_base_free(base); close(fd); return 0;}

//read_fifo#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <fcntl.h>#include <event2/event.h>// 读取回调函数 void read_cb(evutil_socket_t fd, short what, void arg){ // 读管道 char buf[1024] = {0}; int len = read(fd, buf, sizeof(buf)); printf("data len = %d, buf = %s\n", len, buf); printf("read event: %s", what & EV_READ ? "Yes" : "No");//对what类型对判断}int main(int argc, const char argv[]){ unlink("myfifo"); //创建有名管道 mkfifo("myfifo", 0664); // open file int fd = open("myfifo", O_RDONLY | O_NONBLOCK); if(fd == -1) { perror("open error"); exit(1); } // 读管道 struct event_base base = NULL; base = event_base_new(); // 创建事宜 struct event ev = NULL; ev = event_new(base, fd, EV_READ | EV_PERSIST, read_cb, NULL); // 添加事宜 event_add(ev, NULL); // 事宜循环 event_base_dispatch(base); // 开释资源 event_free(ev); event_base_free(base); close(fd); return 0;}

利用gcc对文件编译 -levevt引用libevent库

gcc read_fifo.c -o read -levent

gcc write_fifo.c -o write -levent

./read ./write 依次实行即可

标签:

相关文章