MST

星途 面试题库

面试题:网络编程之libev基础应用

请简述libev库中核心的数据结构,以及如何使用libev来创建一个简单的事件循环并监听一个TCP套接字的连接事件。
44.5万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试

libev库核心数据结构

  1. ev_loop:事件循环结构体,管理所有注册的事件和调度I/O、定时器等事件。一个应用程序通常只有一个主事件循环实例。
  2. ev_io:用于处理I/O事件,如TCP套接字、文件描述符等。它包含了文件描述符(fd)、事件类型(如读、写事件)以及事件触发时的回调函数。
  3. ev_timer:用于处理定时事件。包含定时时间(延迟时间和重复时间)以及定时器到期时的回调函数。

使用libev创建简单事件循环并监听TCP套接字连接事件示例代码(以C语言为例)

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ev.h>

// 监听套接字的文件描述符
static int listen_fd;

// 当有新连接时的回调函数
static void accept_cb(struct ev_loop *loop, ev_io *w, int revents) {
    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    int client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_addr_len);
    if (client_fd < 0) {
        perror("accept");
        return;
    }
    printf("Accepted new connection: %d\n", client_fd);
    close(client_fd);
}

int main() {
    // 创建事件循环
    struct ev_loop *loop = ev_default_loop(0);

    // 创建监听套接字
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd < 0) {
        perror("socket");
        return 1;
    }

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(12345);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind");
        close(listen_fd);
        return 1;
    }

    if (listen(listen_fd, 5) < 0) {
        perror("listen");
        close(listen_fd);
        return 1;
    }

    // 创建并初始化一个I/O watcher用于监听新连接
    struct ev_io accept_watcher;
    ev_io_init(&accept_watcher, accept_cb, listen_fd, EV_READ);
    ev_io_start(loop, &accept_watcher);

    // 进入事件循环
    ev_run(loop, 0);

    // 清理资源
    ev_io_stop(loop, &accept_watcher);
    close(listen_fd);
    ev_loop_destroy(loop);

    return 0;
}

上述代码实现了以下步骤:

  1. 创建一个事件循环 ev_loop
  2. 创建一个TCP监听套接字,并绑定到指定端口。
  3. 初始化一个 ev_io 结构体 accept_watcher 用于监听监听套接字的读事件(即新连接事件),并指定回调函数 accept_cb
  4. accept_watcher 加入到事件循环中开始监听。
  5. 启动事件循环 ev_run
  6. 当有新连接时,accept_cb 回调函数被调用,打印新连接的文件描述符并关闭该连接。
  7. 最后清理资源,停止 ev_io 监听,关闭监听套接字并销毁事件循环。