linux-libevent

1.libevent 是一个库,底层封装了select,poll,epoll,用起来更方便

libevent底层用的是多线程。-->ldd+可执行文件(可以查看用了哪些共享库)

2.libevent(主要就是检测定时器,信号,i/o方法)的执行流程:

 对于组件来说①句柄就是文件描述符②事件多路分发器:i/o方法实现③事件处理器和事件具体处理器:回调函数(事件具体处理器:I/O框架库提供的事件处理器通常是一个接口,用户需要继承它来实现自己的事件处理器,即具体事件处理器。因此,事件处理器中的回调函数一般被声明为虚函数,以支持用户的扩展。此外,事件处理器一般还提供一个get handle方法,它返回与该事件处理器关联的句柄。那么,事件处理器和句柄有什么关系?当事件多路分发器检测到有事件发生时,它是通过句柄来通知应用程序的。因此,我们必须将事件处理器和句柄绑定,才能在事件发生时获取到正确的事件处理器。)④Reactor:

3.libevent简单的示例(了解接口,参数):libevent检测定时器,信号:

libevent提供的事件(编译要加库-levent):

event_new:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <event.h>//libevent
#include <signal.h>//信号
#include <time.h>//定时器

void sig_cb(int fd, short ev, void* arg)//描述符,事件类型,传给的参数
{
    if ( ev & EV_SIGNAL)//确保是信号的事件EV_SIGNAL
    {
        printf("sig=%d\n",fd);
    }
}
void timeout_cb(int fd, short ev, void* arg)
{
    if( ev & EV_TIMEOUT)//确保是定时事件EV_TIMEOUT
    {
        printf("time out\n");
    }
}
int main()
{
    //1 定义libevent实例
    struct event_base * base = event_init();//初始化实例
//--------------------------------------------------信号事件
    //2 定义事件-->信号事件
    //struct event * sig_ev = evsignal_new(base,SIGINT,sig_cb,NULL);//底层默认是永久性事件EV_PERSIST
    struct event * sig_ev = event_new(base,SIGINT,EV_SIGNAL,sig_cb,NULL);//sig_cb为回调函数,传给的参数是空,EV_SIGNAL为将永久性事件改为信号事件即只触发一次
    //3 添加事件到Libevent
    event_add(sig_ev,NULL);//事件的指针,超时时间(NULL)
//---------------------------------------------------定时的事件
    struct timeval tv = {5,0};//定时5s,每5s触发一次
    //定义事件-->定时的事件
    //struct event * time_ev = evtimer_new(base,timeout_cb,NULL);//底层为定时事件EV_TIMEOUT
    struct event * time_ev = event_new(base,-1,EV_TIMEOUT|EV_PERSIST,timeout_cb,NULL);//描述符定时没描述符为-1,EV_TIMEOUT|EV_PERSIST为给定时事件加上永久性事件
    //添加事件到libevent
    event_add(time_ev,&tv);
//---------------------------------------------------事件循环
    //事件循环---内部调用select/poll/epoll循环检测事件
    event_base_dispatch(base);//启动循环,参数为实例,没有事件自动结束-->底层调用epoll_wait会阻塞
    event_free(time_ev);//释放定时事件
    event_free(sig_ev);//释放信号事件
    event_base_free(base);//将bsae释放
    exit(0);
}

4.libevent与tcp,作为服务器端(i/o事件):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <event.h>
#include <time.h>

struct mess//为每一个描述符准备这个结构体空间,存放事件,延长生长周期,(存放描述符所要的数据)
{
    struct event * ev;//事件-->存放事件,记住事件
    //char data[1024];//自定义-->存数据
    //int c;//自定义-->存放描述符的值
};
int socket_init();
void recv_data(int c, short ev, void* arg)//接收数据
{
    struct mess * p = (struct mess*)arg;

    if( ev & EV_READ)
    {
        char buff[128] = {0};
        int n = recv(c,buff,127,0);
        if ( n <= 0 )
        {
            event_free(p->ev);//libevent移除 event_free()
            free(p);
            close(c);
            printf("client close\n");
            return;
        }

        printf("buff=%s\n",buff);
        send(c,"ok",2,0);
    }
}
void accept_client(int sockfd, short ev, void* arg)//接收客户端,接收后得到的连接套接子,要先进行libevent检测后再返回
{
    struct event_base* base = (struct event_base*)arg;//参数为arg
    if( ev & EV_READ )//现阶段只关注读
    {
        int c = accept(sockfd,NULL,NULL);
        if ( c < 0 )
        {
            return;
        }

        //定义事件-->这样移除没法移除,移除得是个指针
        //struct event * c_ev=event_new(base,c,EV_READ|EV_PERSIST,recv_data,NULL);
        //event_add(c_ev,NULL);//添加事件到libevent

        struct mess * p = (struct mess*)malloc(sizeof(struct mess));
        //定义事件
        p->ev = event_new(base,c,EV_READ|EV_PERSIST,recv_data,p);//放入结构体
        event_add(p->ev,NULL);//添加事件到libevent
        //p->c = c;//p所需的其他数值可以继续添加
        
    }

}
int main()
{
    int sockfd = socket_init();
    if ( sockfd == -1 )
    {
        exit(1);
    }

    //1 定义libevent实例
    struct event_base * base = event_init();

    //添加sockfd,到libevent
    struct event* sock_ev = event_new(base,sockfd,EV_READ|EV_PERSIST,accept_client,base);//有读事件进行这一行
    event_add(sock_ev,NULL);//将新事件加到libevent中

    event_base_dispatch(base);//启动事件循环 while( 1 ) epoll_wait, 阻塞
    event_free(sock_ev);
    event_base_free(base);
    close(sockfd);
    exit(0);
}
int socket_init()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if( sockfd == -1 )
    {
        return -1;
    }

    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
    if ( res == -1)
    {
        printf("bind err\n");
        return -1;
    }

    res = listen(sockfd,5);
    if( res == -1)
    {
        return -1;
    }

    return sockfd;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值