关闭

libevent学习.1

206人阅读 评论(0) 收藏 举报
分类:

版本: 2.0.22

ECHO服务器(单线程异步例子)

#include <stdlib.h>
#include <string> // C++
#include <string.h> // C
#include <unistd.h>
#include <event.h>
#include <evutil.h>
#include <event2/listener.h>

void cb_read(struct bufferevent *bev, void *ctx) {
    evbuffer *input, *output;
    input = bufferevent_get_input(bev);
    output = bufferevent_get_output(bev);

    char *str = evbuffer_readln(input, NULL, EVBUFFER_EOL_CRLF);
    if (str == NULL) {
        return;
    }

    if (strcmp(str, "bye") == 0) {
        bufferevent_free(bev);
    } else if (strcmp(str, "exit") == 0) {
        event_base *base = bufferevent_get_base(bev);

        // memory leak (had pending bufferevent)
        event_base_loopexit(base, NULL);
    } else {
        std::string s(str);

        s.insert(0, "resp: ");
        s.append("\n");
        bufferevent_write(bev, s.data(), s.size());
    }
    free(str);
}

void cb_write(struct bufferevent *bev, void *ctx) {

}

void cb_error(struct bufferevent *bev, short what, void *ctx) {

    bufferevent_free(bev);
}

void cb_accept(evconnlistener *lev, evutil_socket_t fd, sockaddr *sa, int socklen, void *ctx) {
    event_base *base = evconnlistener_get_base(lev);

    bufferevent *bufev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bufev, cb_read, cb_write, cb_error, NULL);
    bufferevent_enable(bufev, EV_PERSIST|EV_READ|EV_WRITE);
}

void cb_accept_error(evconnlistener *lev, void *ctx) {
    event_base *base = evconnlistener_get_base(lev);

    event_base_loopexit(base, NULL);
}

int do_server(u_short port) {
    event_base *base = event_base_new();
    if (base == NULL) {
        return -1;
    }

    sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl(0);
    sa.sin_port = htons(port);

    evconnlistener *lev = evconnlistener_new_bind(base, cb_accept, NULL, 
        LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1/*BACKLOG*/,
        (sockaddr *)&sa, sizeof(sa));
    if (lev == NULL) {
        event_base_free(base);
        return -2;
    }
    evconnlistener_set_error_cb(lev, cb_accept_error);

    event_base_dispatch(base);

    evconnlistener_free(lev);
    event_base_free(base);
    return 0;
}

int main() {
    return do_server(1256);
}

已知问题:

服务器主动退出事件循环时,与event_base关联的bufferevent不会释放,网上有人说没必要,因为即将退出程序,没必要回收,所以尚未找到“优雅”的退出方式。

参考资料:

Libevent学习笔记(一):基本使用

libevent 接收TCP连接

libevent-2.0.21笔记

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:284735次
    • 积分:4225
    • 等级:
    • 排名:第7536名
    • 原创:130篇
    • 转载:23篇
    • 译文:0篇
    • 评论:91条
    文章分类
    最新评论