libevent深入浅出
  • Libevent深入浅出
  • 1 Libevent官方
  • 2 epoll
    • 2.1 流-IO操作-阻塞
    • 2.2 解决阻塞死等待的办法
    • 2.3 什么是epoll
    • 2.4 epollAPI
    • 2.5 触发模式
    • 2.6 简单的epoll服务器
  • 3 epoll和reactor
    • 3.1 reactor反应堆模式
    • 3.2 epoll的反应堆模式实现
  • 4 event_base
    • 4.1 创建event_base
    • 4.2 检查event_base后端
    • 4.3 释放event_base
    • 4.4 event_base优先级
    • 4.5 event_base和fork
  • 5 事件循环event_loop
    • 5.1 运行循环
    • 5.2 停止循环
    • 5.3 转储event_base的状态
  • 6 事件event
    • 6.1 创建事件
    • 6.2 事件的未决和非未决
    • 6.3 事件的优先级
    • 6.4 检查事件状态
    • 6.5 一次触发事件
    • 6.6 手动激活事件
    • 6.7 事件状态之间的转换
  • 7 数据缓冲Bufferevent
    • 7.1 回调和水位
    • 7.2 延迟回调
    • 7.3 bufferevent 选项标志
    • 7.4 使用bufferevent
    • 7.5 通用bufferevent操作
      • 7.5.1 释放bufferevent操作
      • 7.5.2 操作回调、水位和启用/禁用
      • 7.5.3 操作bufferevent中的数据
      • 7.5.4 bufferevent的清空操作
  • 8 数据封装evBuffer
    • 8.1 创建和释放evbuffer
    • 8.2 evbuffer与线程安全
    • 8.3 检查evbuffer
    • 8.4 向evbuffer添加数据
    • 8.5 evbuffer数据移动
    • 8.6 添加数据到evbuffer前
  • 8 链接监听器evconnlistener
    • 8.1 创建和释放 evconnlistener
    • 8.2 启用和禁用 evconnlistener
    • 8.3 调整 evconnlistener 的回调函数
    • 8.4 检测 evconnlistener
    • 8.5 侦测错误
  • 9 libevent常用设置
    • 9.1 日志消息回调设置
    • 9.2 致命错误回调设置
    • 9.3 内存管理回调设置
    • 9.4 锁和线程的设置
    • 9.5 调试事件的使用
  • 10 基于libevent服务器
    • 10.1 Hello_World服务器(基于信号)
    • 10.2 基于事件服务器
    • 10.3 回显服务器
    • 10.3 libevent实现http服务器
    • 10.4 libevent实现TCP/IP服务器
Powered by GitBook
On this page

Was this helpful?

  1. 10 基于libevent服务器

10.3 回显服务器

#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>

#include <arpa/inet.h>

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

static void
echo_read_cb(struct bufferevent *bev, void *ctx)
{
        /* This callback is invoked when there is data to read on bev. */
        struct evbuffer *input = bufferevent_get_input(bev);
        struct evbuffer *output = bufferevent_get_output(bev);

        /* Copy all the data from the input buffer to the output buffer. */
        evbuffer_add_buffer(output, input);
}

static void
echo_event_cb(struct bufferevent *bev, short events, void *ctx)
{
        if (events & BEV_EVENT_ERROR)
                perror("Error from bufferevent");
        if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
                bufferevent_free(bev);
        }
}

static void
accept_conn_cb(struct evconnlistener *listener,
    evutil_socket_t fd, struct sockaddr *address, int socklen,
    void *ctx)
{
        /* We got a new connection! Set up a bufferevent for it. */
        struct event_base *base = evconnlistener_get_base(listener);
        struct bufferevent *bev = bufferevent_socket_new(
                base, fd, BEV_OPT_CLOSE_ON_FREE);

        bufferevent_setcb(bev, echo_read_cb, NULL, echo_event_cb, NULL);

        bufferevent_enable(bev, EV_READ|EV_WRITE);
}

static void
accept_error_cb(struct evconnlistener *listener, void *ctx)
{
        struct event_base *base = evconnlistener_get_base(listener);
        int err = EVUTIL_SOCKET_ERROR();
        fprintf(stderr, "Got an error %d (%s) on the listener. "
                "Shutting down.\n", err, evutil_socket_error_to_string(err));

        event_base_loopexit(base, NULL);
}

int
main(int argc, char **argv)
{
        struct event_base *base;
        struct evconnlistener *listener;
        struct sockaddr_in sin;

        int port = 9876;

        if (argc > 1) {
                port = atoi(argv[1]);
        }
        if (port<=0 || port>65535) {
                puts("Invalid port");
                return 1;
        }

        base = event_base_new();
        if (!base) {
                puts("Couldn't open event base");
                return 1;
        }

        /* Clear the sockaddr before using it, in case there are extra
         * platform-specific fields that can mess us up. */
        memset(&sin, 0, sizeof(sin));
        /* This is an INET address */
        sin.sin_family = AF_INET;
        /* Listen on 0.0.0.0 */
        sin.sin_addr.s_addr = htonl(0);
        /* Listen on the given port. */
        sin.sin_port = htons(port);

        listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
            LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
            (struct sockaddr*)&sin, sizeof(sin));
        if (!listener) {
                perror("Couldn't create listener");
                return 1;
        }
        evconnlistener_set_error_cb(listener, accept_error_cb);

        event_base_dispatch(base);
        return 0;
}
Previous10.2 基于事件服务器Next10.3 libevent实现http服务器

Last updated 6 years ago

Was this helpful?