Libevent 的简单实用

轻量级网络库Libevent对高效的I/O进行了封装,提供统一的API,我们调用API就会很方便,要搞清楚每个API背后的操作。
     什么是高效的I/O???       
                    如Linux中独有的epoll,windows的IOCP,BSD的Kqueque

我使用的是libevent2.0.21版本, Libevent2.0版本以后提供了bufferevent 提供了易用的API,bufferevent 解决了粘包等问题,我们在写程序的时候就不用自己管理缓冲区了。

关于tcp网络socket编程的一系列流程 可以查看

接下来说libevent的使用教程

  • 第一步
    //创建一个event_base
    struct event_base *base = event_base_new();

     

  • 第二步

    //创建并绑定一个event
    struct event *event_listen = event_new(base, sockfd, EV_READ|EV_PERSIST, CallBack_Func, (void*)base);

     

  • 第三步

    //添加事件
    event_add(even_listen, NULL);

     

  • 第四步 

    //事件循环
    event_base_dispatch(base);

     

  • 第五步   
    1.设置描述符c(accept之后返回的描述符fd)为​nonblocking
                  Linux中将socket设置为非阻塞   int flag = fcntl(sockfd, F_GETFL, 0);      fcntl(sockfd, F_SETFL, flag|O_NONBLOCK);
    2.创建一个bufferevent,struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    3.调用bufferevent_setcb(bev, Read_cb, Write_cb, bufferent_event_erro3, NULL);
    4.调用bufferevent_enable(bev, EV_READ | EV_RWRITE | EV_PERSIST);  启用read/write事件

下边就是整个服务器调用libevent的代码编程

//
// Created by yanpan on 2019/4/26.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <event.h>
using namespace std;

//#define address 127.0.0.1
//#define port 8888


void OnRead(struct bufferevent *bev, void *arg)
{
    cout<<"bufferent_event_ok happened ....."<<endl;
    evutil_socket_t sfd = bufferevent_getfd(bev);
    int recv_size = 0;
    char buf[100];
    memset(buf,0,sizeof(char)*100);
    std::cout<<"enter buf==="<<buf<<std::endl;
    if ((recv_size = bufferevent_read(bev, buf, 100)) > 0) // 读取前100位的数据
    {
    }
    std::cout<<"get buf==="<<buf<<std::endl;
    int write_num = bufferevent_write(bev, "ok", 2);
    cout << write_num << " characters written" << endl;
}


void bufferent_event_erro3(struct bufferevent *bev, short event, void *arg)
{
    evutil_socket_t sfd = bufferevent_getfd(bev);
    bufferevent_free(bev);
}

void OnAccept(int sockfd, short iEvent, void *arg)
{
    cout<< "OnAccept happended >>>>> "  <<endl;
    struct sockaddr_in cli;
    socklen_t len = sizeof(cli);
    evutil_socket_t fd = accept(sockfd, (struct sockaddr*)&cli, &len);
    if(-1 == fd)
    {
        cout<< "fd error" <<endl;
        return;
    }
    struct event_base* base = static_cast<event_base*> (arg);

    int flag = EV_READ | EV_PERSIST;
    evutil_make_socket_nonblocking(fd);   //将fd设置成非阻塞
    struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev, OnRead, NULL, bufferent_event_erro3, NULL);
    bufferevent_enable(bev, flag);
}
int main()
{
    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd)
        return 0;

    struct sockaddr_in ser;
    ser.sin_family = PF_INET;
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    ser.sin_port = htons(8888);

    int ret = bind(sockfd, (struct sockaddr*)&ser, sizeof(ser));
    if(-1 == ret)
        return 0;
    int listenfd = listen(sockfd, 5);
    if(-1 == listenfd)
        return 0;
    //初始化base
    struct event_base* base = event_base_new();

    struct event *even_listen = event_new(base, sockfd, EV_READ|EV_PERSIST, OnAccept, (void*)base);


    //添加事件
    event_add(even_listen, NULL);

    //事件循环
    event_base_dispatch(base);
    return 0;
}

坚持✊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值