面试题答案
一键面试- 初始化libevent库
struct event_base *base = event_base_new(); if (!base) { // 处理初始化失败 return 1; }
- 创建监听套接字
int listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) { // 处理套接字创建失败 event_base_free(base); return 1; } struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(SERVER_PORT); if (bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { // 处理绑定失败 close(listen_fd); event_base_free(base); return 1; } if (listen(listen_fd, BACKLOG) < 0) { // 处理监听失败 close(listen_fd); event_base_free(base); return 1; }
- 注册监听事件
- 定义一个监听事件的回调函数,例如:
static void accept_conn_cb(evutil_socket_t listen_fd, short event, void *arg) { struct event_base *base = (struct event_base *)arg; int client_fd = accept(listen_fd, NULL, NULL); if (client_fd < 0) { // 处理接受连接失败 return; } // 为新连接创建并注册事件 struct event *client_event = event_new(base, client_fd, EV_READ | EV_PERSIST, read_cb, (void *)client_fd); if (!client_event) { // 处理事件创建失败 close(client_fd); return; } if (event_add(client_event, NULL) < 0) { // 处理事件添加失败 event_free(client_event); close(client_fd); return; } }
- 注册监听事件:
struct event *listen_event = event_new(base, listen_fd, EV_READ | EV_PERSIST, accept_conn_cb, (void *)base); if (!listen_event) { // 处理事件创建失败 close(listen_fd); event_base_free(base); return 1; } if (event_add(listen_event, NULL) < 0) { // 处理事件添加失败 event_free(listen_event); close(listen_fd); event_base_free(base); return 1; }
- 设计客户端连接的回调函数
- 读取回调函数:
static void read_cb(evutil_socket_t client_fd, short event, void *arg) { char buf[BUFFER_SIZE]; int n = recv(client_fd, buf, sizeof(buf), 0); if (n <= 0) { // 处理读取错误或连接关闭 if (n < 0) { // 处理具体错误 } close(client_fd); return; } buf[n] = '\0'; // 处理接收到的数据 // 例如可以在这里进行数据解析、转发等操作 // 处理完数据后,如果需要继续接收数据,可以再次注册读事件 struct event *client_event = event_new((struct event_base *)arg, client_fd, EV_READ | EV_PERSIST, read_cb, (void *)client_fd); if (!client_event) { // 处理事件创建失败 close(client_fd); return; } if (event_add(client_event, NULL) < 0) { // 处理事件添加失败 event_free(client_event); close(client_fd); return; } }
- 写入回调函数(如果需要发送数据):
static void write_cb(evutil_socket_t client_fd, short event, void *arg) { // 从缓冲区获取数据并发送 // 例如: char *send_buf = (char *)arg; int n = send(client_fd, send_buf, strlen(send_buf), 0); if (n <= 0) { // 处理发送错误 close(client_fd); return; } // 处理发送成功,可能需要更新缓冲区等操作 // 如果还有数据要发送,可以再次注册写事件 }
- 进入事件循环
event_base_dispatch(base);
- 清理资源
- 在程序结束时,释放资源:
event_base_free(base); close(listen_fd);
在整个过程中,利用libevent
库的事件驱动机制,通过注册不同类型的事件(如读、写事件)和相应的回调函数,实现对多个客户端并发连接的高效处理。EV_PERSIST
标志使得事件在触发后不会自动删除,以便持续处理后续的事件。