libevent服务器

libevent服务器

介绍

首先包含两个头文件

#include <event2/event.h>
#include <event2/bufferevent.h>

base

base是里边的基本东西,必须要有的,通过以下接口创建和销毁
event_base_new 创建
event_base_free 释放

event

event是base之后需要有的,对于服务器来说就是设置监听用的
event_new 创建
event_free 释放
event_add 添加事件
event_base_dispatch 事件循环

bufferevent

bufferevent这个就是带有缓冲区的事件了,这里主要介绍以下几个
bufferevent_socket_new 创建
bufferevent_free 释放
bufferevent_setcb 设置回调
bufferevent_enable 启用bufferevent
bufferevent_read 读取
bufferevent_write 写入

大概就这些了

Demo

#include <iostream>
#include <unistd.h>
#include <event2/event.h>
#include <event2/bufferevent.h>

void read_cb(struct bufferevent *bev, void *ctx)
{
    std::string strBuf;

    int cfd = bufferevent_getfd(bev);
    std::cout << "cfd: " << cfd << "send: ";
    while(1)
    {
        char buf[1024] = { 0 };
        int n = 0;
        n = bufferevent_read(bev, buf, sizeof(buf));
        if(n == -1)
        {
            std::cout << "bufferevent_read error" << std::endl;
            return;
        }
        else if(n == 0)
        {
            break;
        }
        else
        {
            std::cout << buf;
            strBuf += buf;
        }
        
    }

    if(bufferevent_write(bev, strBuf.c_str(), strBuf.size()) == -1)
    {
        //error
        std::cout << "bufferevent_write error" << std::endl;
    }
    
}
void write_cb(struct bufferevent *bev, void *ctx)
{
    std::cout << "send finish" << std::endl;
}

void error_cb(struct bufferevent *bev, short what, void *ctx)
{
    int cfd = bufferevent_getfd(bev);

    if(what & BEV_EVENT_ERROR)
    {
        std::cout << "cfd: " << cfd << "error!" << std::endl;
    }
    else if(what & BEV_EVENT_EOF)
    {
        std::cout << "cfd: " << cfd << "connection closed!" << std::endl;
    }
    else if(what & BEV_EVENT_TIMEOUT)
    {
        std::cout << "cfd: " << cfd << "timeout!" << std::endl;
    }

    bufferevent_free(bev);
}


void accept_cb(evutil_socket_t lfd, short event, void* arg)
{
    struct event_base* base = (struct event_base*)arg;

    struct sockaddr_in client_in;
    socklen_t client_size = sizeof(client_in);

    int cfd = accept(lfd, (sockaddr*)&client_in, &client_size);
    if(cfd == -1)
    {
        perror("accept err:");
        return;
    }
    
    struct bufferevent* bev = bufferevent_socket_new(base, cfd, BEV_OPT_CLOSE_ON_FREE);
    
    bufferevent_setcb(bev, read_cb, write_cb, error_cb, NULL);
    bufferevent_enable(bev, EV_READ | EV_PERSIST);

}

int main()
{
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if(lfd == -1)
    {
        perror("socket err:");
        return -1;
    }

    struct sockaddr_in server_in;
    server_in.sin_addr.s_addr = htonl(INADDR_ANY);
    server_in.sin_family = AF_INET;
    server_in.sin_port = htons(33333);

    if(bind(lfd, (const sockaddr*)&server_in, sizeof(server_in)) == -1)
    {
        perror("bind err:");
        return -1;
    }

    if(listen(lfd, 30) == -1)
    {
        perror("listen err:");
        return -1;
    }

    //evutil_make_socket_nonblocking(lfd);

    struct event_base* base = event_base_new();

    struct event* lev = event_new(base, lfd, EV_WRITE | EV_READ | EV_PERSIST, accept_cb, (void*)base);
    
    event_add(lev, NULL);
    
    event_base_dispatch(base);

    event_base_free(base);

    return 0;
}
上一篇:使用Python分析nginx日志


下一篇:以滴滴出行为例,谈谈如何分析用户评论