面试题答案
一键面试- 初始化libevent库:
- 使用
event_init()
函数初始化libevent库环境。示例代码:
struct event_base *base = event_init(); if (!base) { perror("event_init"); return 1; }
- 使用
- 创建UDP socket:
- 使用
socket(AF_INET, SOCK_DGRAM, 0)
创建UDP socket。示例代码:
int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("socket"); return 1; }
- 使用
- 绑定端口:
- 构建
sockaddr_in
结构体,设置地址和端口等信息,然后使用bind()
函数将socket绑定到指定端口。示例代码:
struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(SERVER_PORT); if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("bind"); close(sockfd); return 1; }
- 构建
- 创建事件:
- 使用
event_new()
函数创建一个事件,指定要监听的socket、事件类型(如EV_READ|EV_PERSIST
表示读事件且持续监听)以及事件触发时的回调函数。示例代码:
struct event *ev = event_new(base, sockfd, EV_READ|EV_PERSIST, read_callback, (void *)&sockfd); if (!ev) { perror("event_new"); event_base_free(base); close(sockfd); return 1; }
- 其中
read_callback
是自定义的处理接收到数据的回调函数,原型一般为void read_callback(int fd, short event, void *arg)
。
- 使用
- 添加事件到事件循环:
- 使用
event_add()
函数将创建的事件添加到事件循环中。示例代码:
if (event_add(ev, NULL) < 0) { perror("event_add"); event_free(ev); event_base_free(base); close(sockfd); return 1; }
- 使用
- 进入事件循环:
- 使用
event_base_dispatch()
函数启动事件循环,等待事件发生并处理。示例代码:
event_base_dispatch(base);
- 使用
- 处理接收到的数据(在回调函数中):
- 在
read_callback
回调函数中,使用recvfrom()
函数从UDP socket接收数据。示例代码:
void read_callback(int fd, short event, void *arg) { char buffer[BUFFER_SIZE]; struct sockaddr_in cliaddr; socklen_t len = sizeof(cliaddr); int n = recvfrom(fd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len); buffer[n] = '\0'; // 在这里处理接收到的数据buffer }
- 在
- 清理资源:
- 当不再需要时,使用
event_free()
释放事件,event_base_free()
释放事件基,close()
关闭socket。示例代码:
event_free(ev); event_base_free(base); close(sockfd);
- 当不再需要时,使用