当前位置:   article > 正文

libevent介绍和使用_libevnet

libevnet

libevent介绍

libevent 是一个开源的事件通知库,它提供了一个跨平台的抽象接口,libevnet处理的事件包括网络IO事件,定时事件以及信号事件。它可以在不同的操作系统上使用,包括Linux、Windows和Mac OS X等。libevent 的主要目的是提供高效的事件通知机制,用户无需关注平台检测处理事件的机制的差异,只需关注事件的具体处理。它可以用于编写服务器、客户端和其他网络应用程序。

libevent使用

网络中有很多说明libevent如何编译的文章,我就不介绍libevent的如何编译安装,首先我们使用一段代码来直观的展示libevent是如何使用的,然后在介绍libevent的流程和libevent的关键API。下面这段代码展示的是服务器接收客户端的消息,并返回消息给客户端。

#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include "event2/event.h"
void socket_read_cb(int fd, short events, void *arg);
//接收到客户端的回调处理
void socket_accept_cb(int fd, short events, void* arg)
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    evutil_socket_t clientfd = accept(fd, (struct sockaddr*)&addr, &len);
    evutil_make_socket_nonblocking(clientfd);//设置客户端socket为非阻塞模式
    printf("accept a client %d\n", clientfd);
    struct event_base* base = (struct event_base*)arg;
    struct event *ev = event_new(NULL, -1, 0, NULL, NULL);//分配一个事件
    event_assign(ev, base, clientfd, EV_READ | EV_PERSIST,
                 socket_read_cb, (void*)ev);
    event_add(ev, NULL);//将事件加入到事件管理器中进行管理
}
 
 //客户端发送数据的回调处理
void socket_read_cb(int fd, short events, void *arg)
{
    char msg[4096];
    struct event *ev = (struct event*)arg;
    int len = read(fd, msg, sizeof(msg) - 1);
    if( len <= 0 )
    {
        printf("client fd:%d disconnect\n", fd);
        event_free(ev);
        close(fd);
        return;
    }
    msg[len] = '\0';
    printf("recv the client msg: %s", msg);
    char reply_msg[4096] = "recvieced msg: ";
    strcat(reply_msg + strlen(reply_msg), msg);
    write(fd, reply_msg, strlen(reply_msg));
}
 
int socket_listen(int port)
{
    int errno_save;
    evutil_socket_t listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1)
        return -1;
    evutil_make_listen_socket_reuseable(listenfd);//设置端口和地址为复用
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = 0;
    sin.sin_port = htons(port);
    if (bind(listenfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
        evutil_closesocket(listenfd);
        return -1;
    }
    if (listen(listenfd, 5) < 0) {
        evutil_closesocket(listenfd);
        return -1;
    }
    evutil_make_socket_nonblocking(listenfd);//设置socket未非阻塞模式
    return listenfd;
}

int main(int argc, char** argv)
{
    int listenfd = socket_listen(8080);
    if (listenfd == -1)
    {
        printf("socket_listen error\n");
        return -1;
    }
    struct event_base* base = event_base_new();//创建事件管理器对象
    struct event* ev_listen = event_new(base, listenfd, EV_READ | EV_PERSIST,
                                        socket_accept_cb, base);//创建监听事件对象
    event_add(ev_listen, NULL);//将监听事件对象加入到事件管理器中进行管理
    event_base_dispatch(base);//消息循环(代码会被阻塞到此处)
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

libevent流程

Libevent框架本质上是一个典型的Reactor模式,所以只需要弄懂Reactor模型,libevent就八九不离十了。
Reactor模式,是一种事件驱动机制。应用程序需要提供相应的接口并注册到Reactor上,如果相应的事件发生,Reactor将主动调用应用程序注册的接口,这些接口又称为“回调函数”。
在Libevent中也是一样,向Libevent框架注册相应的事件和回调函数;当这些事件发生时,Libevent会调用这些回调函数处理相应的事件(I/O读写、定时和信号)。

(1) 创建事件管理器对象
(2) 创建事件对象,并将事件加入到事件管理器对象中
(3) 消息事件循环
  • 1
  • 2
  • 3

在这里插入图片描述
在网络事件框架中,我们主要关注2个问题:事件的检测和事件的处理,同样,libevent也主要关注这2个方面,我们使用libevent,可以仅仅使用libevent的事件检测,事件处理的逻辑由我们自己来写,或者事件检测和事件处理都使用libevent提供的方式。
(1)事件的检测
事件管理器对象负责检测事件是否发生,比如是否发生了IO事件(比如是否有客户端的连接,客户端是否发送了数据),定时器事件是否超时等。
(2)事件的处理
当检测到事件发生时,我们应该对事件进行处理,以下是一些示例
a.连接建立时:构建黑白名单,限制最大连接数
b.连接断开时:释放连接和对应的资源
c.数据到达时:数据的处理
因此我们将libevent的API分为这2个方面

libevent API

事件检测相关

事件管理器API

event_base_new();//创建事件管理器对象
event_base_new_with_config();//带配置的事件管理器对象
event_base_free();//销毁事件管理器对象
event_base_loop();//事件循环
event_base_loopbreak();//事件循环退出
event_base_loopexit();//事件循环退出
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

事件API

event_new();//构建事件对象
event_free();//销毁事件对象
event_add();//注册事件
event_del();//注销事件
event_assign();//修改事件
  • 1
  • 2
  • 3
  • 4
  • 5

事件操作API

连接接收

事件监听器对象用于服务器监听客户端的对象,对象为evconnlisterner

evconnlisterner_new();//创建事件监听器对象
evconnlisterner_new_bind();//创建事件监听器对象
evconnlisterner_free();//销毁事件监听器对象
evconnlisterner_set_error_cb();//设置错误回调
  • 1
  • 2
  • 3
  • 4

读,写,连接操作

libevent的读写和客户端连接操作主要使用bufferevent对象来进行操作的。

bufferevent_socket_new();//创建bufferevent对象
bufferevent_setcb();//设置bufferevent对象的事件回调(读,写,错误回调)
bufferevent_enable();//注册事件类型
bufferevent_disable();//注销事件类型
bufferevent_get_input();//获取读缓冲区
bufferevent_get_output();//获取写缓冲区
bufferevent_read();//读缓冲区
bufferevent_write();//写缓冲区
bufferevent_socket_connect();//连接操作
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/458533
推荐阅读
  

闽ICP备14008679号