ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

libev使用简述

2021-09-12 20:32:54  阅读:291  来源: 互联网

标签:struct int libev watcher 简述 io 使用 ev loop


官方示例

// libev需要的头文件
#include <ev.h>
#include <stdio.h>
 
// 建立需要监听的事件,这些事件类型是libev提供的
//ev_io为监听控制台输入,ev_timer为时间事件
ev_io stdin_watcher;
ev_timer timeout_watcher;
 
// 以下为自定义的回调函数,当触发监听事件时,调用执行对应的函数
 
// ev_io事件的回调函数,当有输入流stdin时,调用函数
static void stdin_cb (EV_P_ ev_io *w, int revents)
{
puts ("stdin ready");
//对ev_io事件的监控不会自动停止,需要手动在需要的时候停止
ev_io_stop (EV_A_ w);
 
//整体的loop事件在所有监控停止时停止,也可以手动关闭全部的ev_run
ev_break (EV_A_ EVBREAK_ALL);
}
 
// 时间事件的自定义回调函数,可定时触发
static void timeout_cb (EV_P_ ev_timer *w, intrevents)
{
puts ("timeout");
//关闭还在运行的ev_run
ev_break (EV_A_ EVBREAK_ONE);
}
 
int main (void)
{
//定义默认的 event loop,它就像一个大容器,可以装载着很多事件不停运行
struct ev_loop *loop = EV_DEFAULT;
 
// 初始化ev_io事件监控,设置它的回调函数,,和stdin
ev_io_init (&stdin_watcher, stdin_cb,0, EV_READ);
//将ev_io事件放到event loop里面运行
ev_io_start (loop, &stdin_watcher);
 
// 初始化ev_timer事件监控,设置它的回调函数,间隔时间,是否重复
ev_timer_init (&timeout_watcher, timeout_cb, 5.5,0.);
//将ev_timer事件放到event loop里面运行
ev_timer_start (loop, &timeout_watcher);
 
// 大容器event loop整体运行起来
ev_run (loop, 0);
 
// ev_run运行结束之后,才会运行到这里
return 0;
}

监听了     控制台输入事件和定时器事件

如果5.5s内没输入,打印timeout

控制台输入了,打印stdin ready

 

使用的思路:

  • 创建ev_xxx监控器类型
  • ev_xxx_init注册该监控器感兴趣的事件,设置它的回调函数和其他参数
  • ev_xxx_start把该监控器放入事件驱动容器
  • ev_run事件驱动容器运行

向libev注册感兴趣的events,比如Socket事件,libev会对所注册的事件进行管理,并在事件发生时触发相应的程序

libev实现简单服务端

监听到客服端连接事件  会初始化通信socket,打印someone connected,然后注册数据接收事件

监听到数据接收事件,会转发该数据给客服端

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <netinet/in.h>
#include <strings.h>
#include <ev.h>


#define PORT 8333

#define BUFFER_SIZE 1024

//与客服端数据交换
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    char buffer[BUFFER_SIZE];
    ssize_t read;

    if(EV_ERROR & revents)
    {
        printf("error event in read");
        return;
    }

    read = recv(watcher->fd, buffer, BUFFER_SIZE, 0);

    if(read < 0)
    {
        printf("read error,errno:%d\n", errno);
        return;
    }
    else if(0 == read)
    {
        printf("someone disconnected.errno:%d\n", errno);
        ev_io_stop(loop,watcher);//停止
        free(watcher);
        return;
    }
    else
    {
        printf("get the message:%s\n", buffer);
    }

    send(watcher->fd, buffer, read, 0);
    bzero(buffer, read);
}

//初始化通信socket,成功就打印"someone connected"
void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    struct sockaddr_in client_addr;
    socklen_t client_len = sizeof(client_addr);
    int client_sd;
    struct ev_io *w_client = (struct ev_io*) malloc (sizeof(struct ev_io));

    if(EV_ERROR & revents)
    {
        printf("error event in accept\n");
        return;
    }

    client_sd = accept(watcher->fd, (struct sockaddr *)&client_addr, &client_len);
    if (client_sd < 0)
    {
        printf("accept error\n");
        return;
    }


    printf("someone connected \n");

    ev_io_init(w_client, read_cb, client_sd, EV_READ);//socket事件监控器注册了数据读取事件
    ev_io_start(loop, w_client);
}

int main()
{
    int sd = -1;
    struct sockaddr_in addr;

    if((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("socket error. errno:%d\n", errno);
        return -1;
    }

    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);//#define PORT 8333
    addr.sin_addr.s_addr = INADDR_ANY;

    if(bind(sd, (struct sockaddr*) &addr, sizeof(addr)) != 0)
    {
        printf("bind error.errno:%d\n",errno);
        return -1;
    }

    if(listen(sd, 5) < 0)
    {
        printf("listen error\n");
        return -1;
    }

    
    //上面是监听socket初始化

     struct ev_loop *loop = ev_default_loop(0);//初始化事件驱动池
     struct ev_io socket_watcher;//socket事件监控器

    ev_io_init(&socket_watcher, accept_cb, sd, EV_READ);//EV_READ是监听的事件,连接事件发生,回调函数accept_cb处理
    ev_io_start(loop, &socket_watcher);//放入事件驱动池


    while (1)
    {
        printf("ev_loop working\n") ;
        ev_loop(loop, 0);//一次ev_loop执行一轮事件处理 ,  while (1)实现事件循环处理
    }
    return 0;
}

服务端接收了数据并转发给客户端

 

 客户端接收的

 

 

使用原理

libev通过各种事件监听器watcher对各种类型的事件进行监听

watcher是libev定义的结构体

事件是libev定义的宏

ev_loop的创建,运行,停止

//默认使用EV_DEFAULT类型的loop
struct ev_loop *loop = EV_DEFAULT;
返回一个最基础的ev_loop,并自动完成它的初始化
如果程序中已经执行过该创建,将直接返回之前的创建

也可以用ev_default_loop(EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV);
struct ev_loop *loop = ev_default_loop(0);



ev_run(loop, int flags);
flags的作用,用于设置ev_loop的运行方式
通常设置为0,表示该ev_loop在所有watcher结束后停止,也可以手动break


ev_break (loop,how)
how代表停止的方式:
EVBREAK_ONE:停止最久远的那个ev_run
EVBREAK_ALL:停止所有的ev_run

watcher结构体和共有的标准化函数

用面向对象的思想去理解,以下是"基类"

typedef struct ev_watcher
{
    int active; //是否注册到容器中
    int pending; //已经触发事件但是没有处理
    int priority;
    void *data;	
    void (*cb)(struct ev_loop *loop, struct ev_watcher *w, int revents);
} ev_watcher;

举例:"派生类"ev_io

typedef struct ev_io
{
    int active; 
    int pending;
    int priority;
    void *data;	
    void (*cb)(struct ev_loop *loop, struct ev_io *w, int revents);
    struct ev_watcher_list *next;//装监控器的List,与基类配套

    int fd; //这里的fd,events就是派生类的私有成员,分别表示监听的文件fd和触发的事件(可读还是可写) 
    int events; 
} ev_io;

为了对成员变量使用的语句进行简化,就又写了一个"ev_wrap.c"  也可以这样
typedef structev_io
{
EV_WATCHER_LIST (ev_io)
int fd; 
int events; 
} ev_io;

//共有的标准化函数
typedef void (*)(struct ev_loop *loop, ev_TYPE*watcher, int revents) callback; // 回调函数都是这种类型
ev_init (ev_TYPE *watcher, callback); // 初始化与watcher具体类型无关的部分
ev_TYPE_set (ev_TYPE *watcher, [args]); // 初始化watcher的与类型相关的部分
ev_TYPE_init (ev_TYPE *watcher, callback, [args]); //实现上面两个
ev_TYPE_start (loop, ev_TYPE *watcher); // 在ev_loop中注册watcher
ev_TYPE_stop (loop, ev_TYPE *watcher); // 在ev_loop中注销watcher
ev_set_priority (ev_TYPE *watcher, int priority); // 设置watcher优先级,值域为[-2,2],大的优先
ev_feed_event (loop, ev_TYPE *watcher, int revents);// 跨线程通知,相当于触发了某个事件。
bool ev_is_active (ev_TYPE *watcher); // watcher是否active.
bool ev_is_pending (ev_TYPE *watcher); // watcher是否pending.
int ev_clear_pending (loop, ev_TYPE *watcher); // 清除watcher pending状态并且返回事件


 

标签:struct,int,libev,watcher,简述,io,使用,ev,loop
来源: https://blog.csdn.net/qq_54946614/article/details/120241982

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有