libevent关键函数及知识点梳理

更新时间:2023-07-17 14:12:20 阅读: 评论:0

libevent关键函数及知识点梳理
文财神摆放的最佳方位事件循环控制:主要是开始事件循环和终⽌事件循环
1. 使⽤默认配置开始事件循环: event_ba_dispatch()
2. 开始事件循环,可以设置⼀些参数: event_ba_loop()
3. 指定时间后退出事件循环,处理完回调函数后退出 : event_ba_loopexit()
4. ⽴即退出事件循环: event_ba_loopbreak()
libevent的基本操作单元是事件(event),每个(event)都是下列情况发⽣的集合
去痛风1. ⽂件描述符【已经】可读/可写.
2. ⽂件描述符【变为】可读/可写.(边缘触发模式下)
3. 超时事件时间已到
4. 进程收到信号
5. ⽤户⾃⼰触发事件
事件有⼏个状态
1. 已初始化状态(initialized). 设置好⼀个事件,并且将其关联到⼀个event_ba.
2. 等待状态(pending). 将上述已初始化状态的事件添加到event_ba,事件变为待触发状态.
3. 激活状态(active). 待触发事件的触发条件满⾜,事件变为触发状态.
初始化事件(event_new)时,libevent可关注的事件有下列⼏种,可以是下列事件的组合
1. EV_TIMEOUT : 超时事件.当在添加事件到循环(event_add)的时候设置⼀个超时时间.这个标记超时的时候在回调函数中的事件集合中
被标记.
2. EV_READ : ⽂件描述符可读事件
3. EV_WRITE: ⽂件描述符可写事件
4. EV_SIGNAL: 进程信号事件
5. EV_PERSIST : 将当前事件标记为永久事件,⾮永久事件只能激活⼀次,回调函数执⾏后变为已始化状态.永久事件激活处理后后变为等
待状态.
6. EV_ET : 该⽂件描述符事件使⽤边缘触发⽅式.
⽂件描述符事件(通⽤事件)操作函数
1. 初始化事件: event_new()
2. 添加事件到事件循环 : event_add()
再试一次
3. 从事件循环删除事件,不再监听:event_del()
4. 销毁事件: event_free()
5. 判断事件是否处于pending或者active状态,返回关注的事件或者激活的事件. event_pending()
6. 设置事件的优先级: event_priority_t()
8. 从事件获取event_ba : event_get_ba()
9. 获取关注的事件: event_get_events()
0. 获取事件的回调函数: event_get_callback()
1. 获取事件回调函数的参数: event_get_callback_arg()
2. 获取事件的优先级: event_get_priority()
3. ⼿动激活事件: event_active()
识字大全单纯的定时器事件操作函数(通⽤函数的包装的宏,⽅便使⽤)
1. 初始化事件: evtimer_new()
2. 添加事件到事件循环 : evtimer_add()
3. 从事件循环删除事件,不再监听: evtimer_del()
nvidia控制面板打不开4. 销毁事件: evtimer_del()
5. 判断事件是否处于pending或者active状态,返回关注的事件或者激活的事件. evtimer_pending()单纯的信号事件操作函数(通⽤函数的包装的宏,⽅便使⽤)
1. 初始化事件: evsignal_new()
2. 添加事件到事件循环 : evsignal_add()
3. 从事件循环删除事件,不再监听: evsignal_del()
4. 销毁事件: event_free()
5. 判断事件是否处于pending或者active状态,返回关注的事件或者激活的事件. evsignal_pending()下⾯代码分别演⽰:⽂件描述符事件、超时事件、信号事件
#include <event2/event.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
//保存所有fd对应的event结构体指针.⽅便销毁事件.
//⼀些事件的销毁这⾥就不做处理了.实际程序中注意内存泄露.当事件已经⽆⽤后记得销毁掉.
struct event * fdevent_array[10000];
void tnonblock(int fd)
{
int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
void reuAddr(int fd) {
int yes = 1;
tsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
}
void read_cb(evutil_socket_t fd, short events, void *arg)
{
struct event * myevent;
以一当百if ( events & EV_READ ){
//真正的应⽤中这⾥需要两个⽤户的buffer来保存该连接上的数据.
char buffer[1024];
while(1){
memt( buffer , 0 , 1024);
int nbytes = read( fd , buffer , 1023);
if ( nbytes < 0){
if (errno == EINTR) continue;
if (errno == EAGAIN) break;
printf("client error , fd [%d]\n" , fd);
goto fdclo;
break;
}
if ( nbytes == 0){
printf("client clo , fd [%d]\n" , fd);
goto fdclo;
break;
}
苏轼赤壁赋原文
printf("data from client: %s" , buffer);
write( fd , buffer , nbytes);
}
}
return;
fdclo:
//
myevent = fdevent_array[fd];
event_del(myevent);
event_free(myevent);
clo(fd);
fdevent_array[fd] = NULL;
}
void listen_cb(evutil_socket_t listener, short events , void *arg)
{
if (events & EV_TIMEOUT ){
printf("timer event\n");
}
if (events & EV_READ ){
struct event_ba *ba = arg;
struct sockaddr_storage ss;
socklen_t slen = sizeof(ss);
int fd = accept(listener, (struct sockaddr*)&ss, &slen);
/
/接受了⼀个新客户连接,我们为这个新连接设置⼀个事件
if(fd > 0){
怎么煮冻饺子printf("accept new client fd [%d]\n" , fd);
tnonblock( fd );
//我们现在只关注读事件,将客户端发来的信息回送给客户端.
struct event * client_event = event_new( ba , fd , EV_READ|EV_PERSIST , read_cb , (void*)ba  );  event_add( client_event , NULL);
fdevent_array[fd] = client_event;
}
}
}
void sigint_cb(evutil_socket_t sig, short events , void *arg){
struct event_ba *ba = arg;
if ( events & EV_SIGNAL ){
printf("capture signal [%d]\n" , sig);
event_ba_loopbreak(ba);
}
}
int main(){
struct event_ba * ba = event_ba_new();
//以下代码开启rver监听⼀个本地端⼝.可以将ip改为⾃⼰的服务器以⽅便测试.
int port = 9999;
struct sockaddr_in my_addr;
memt( &my_addr , 0 , sizeof(struct sockaddr_in));
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(port);
my_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
int listen_socket = socket(AF_INET , SOCK_STREAM , 0);
tnonblock(listen_socket);
reuAddr(listen_socket);
bind(listen_socket , (struct sockaddr*)&my_addr , sizeof(struct sockaddr));
listen(listen_socket , 10);
//给监听的socket添加⼀个事件,⽤来accept新连接,关注读事件,并将该event设置为永久事件.设置好回调函数和参数. struct event *listener_event = event_new( ba , listen_socket , EV_READ|EV_PERSIST , listen_cb , (void*)ba); //将监听事件加⼊事件循环.同时我们在监听事件上
加⼀个定时器事件.在回调函数中判断应该接受连接还是定时器触发. struct timeval expire = { 5 , 0 };
event_add( listener_event , &expire);
fdevent_array[listen_socket] = listener_event;
//设置⼀个信号事件,我们监听(ctrl+c的中断信号),收到信号后打印⼀条消息,退出事件循环.
struct event *signal_event = evsignal_new( ba , SIGINT , sigint_cb , (void*)ba);
evsignal_add( signal_event , NULL );
//开始事件循环
event_ba_dispatch( ba );
//
event_ba_free(ba);
}

本文发布于:2023-07-17 14:12:20,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1101451.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:事件   循环   函数   触发   状态   回调
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图