MST

星途 面试题库

面试题:网络编程之Libevent C++基础应用

在使用Libevent通过C++构建高性能事件驱动网络服务时,简述如何创建一个基本的事件监听机制,并且说明如何注册一个处理连接事件的回调函数。
44.3万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试
  1. 创建基本事件监听机制
    • 引入Libevent头文件:
    #include <event2/event.h>
    
    • 初始化Libevent库:
    event_base* base = event_base_new();
    if (!base) {
        // 处理初始化失败
        return 1;
    }
    
    • 创建一个用于监听的文件描述符(例如监听TCP连接的socket):
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd == -1) {
        // 处理socket创建失败
        event_base_free(base);
        return 1;
    }
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(12345);
    sin.sin_addr.s_addr = INADDR_ANY;
    if (bind(listen_fd, (struct sockaddr*)&sin, sizeof(sin)) == -1) {
        // 处理bind失败
        close(listen_fd);
        event_base_free(base);
        return 1;
    }
    if (listen(listen_fd, 10) == -1) {
        // 处理listen失败
        close(listen_fd);
        event_base_free(base);
        return 1;
    }
    
    • 创建一个事件来监听该文件描述符:
    struct event* listen_event = event_new(base, listen_fd, EV_READ | EV_PERSIST, nullptr, nullptr);
    if (!listen_event) {
        // 处理事件创建失败
        close(listen_fd);
        event_base_free(base);
        return 1;
    }
    
  2. 注册处理连接事件的回调函数
    • 定义回调函数:
    static void accept_connection_cb(evutil_socket_t fd, short what, void* arg) {
        // 处理新连接,例如accept新的socket
        int client_fd = accept(fd, nullptr, nullptr);
        if (client_fd != -1) {
            // 对新连接的socket进行处理,如设置非阻塞等
            evutil_make_socket_nonblocking(client_fd);
            // 可以在这里创建新的事件来处理这个client_fd的后续读写事件
        }
    }
    
    • 使用定义好的回调函数重新创建事件:
    struct event* listen_event = event_new(base, listen_fd, EV_READ | EV_PERSIST, accept_connection_cb, nullptr);
    if (!listen_event) {
        // 处理事件创建失败
        close(listen_fd);
        event_base_free(base);
        return 1;
    }
    
    • 添加事件到事件循环:
    if (event_add(listen_event, nullptr) == -1) {
        // 处理添加事件失败
        event_free(listen_event);
        close(listen_fd);
        event_base_free(base);
        return 1;
    }
    
    • 启动事件循环:
    event_base_dispatch(base);
    
    • 最后,记得释放资源:
    event_free(listen_event);
    close(listen_fd);
    event_base_free(base);