epoll多路复用的一个实例程序(C实现)
江奕云 2023-08-09C#
前言epoll是Linux内核提供的一种I/O事件通知机制,它可以用来监视多个文件描述符的I/O事件。与传统的select和poll函数相比,epoll具有更好的性能和扩展性
前言
epoll是Linux内核提供的一种I/O事件通知机制,它可以用来监视多个文件描述符的I/O事件。与传统的select和poll函数相比,epoll具有更好的性能和扩展性。本文将介绍一个使用epoll实现的多路复用实例程序,该程序使用C语言编写。
实现代码
下面是一个基于epoll的多路复用实例程序的代码:
#include#include #include #include #include #include #include #define MAX_EVENTS 1024 #define BUF_SIZE 1024 int main() { int listen_sock, client_sock; struct sockaddr_in server_addr, client_addr; // 创建监听socket listen_sock = socket(AF_INET, SOCK_STREAM, 0); if (listen_sock == -1) { perror("socket"); exit(1); } // 设置地址和端口 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(8080); // 绑定socket int ret = bind(listen_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)); if (ret == -1) { perror("bind"); exit(1); } // 开始监听 ret = listen(listen_sock, 5); if (ret == -1) { perror("listen"); exit(1); } // 创建epoll实例 int epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create1"); exit(1); } // 添加监听socket到epoll实例中 struct epoll_event event; event.events = EPOLLIN; event.data.fd = listen_sock; ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_sock, &event); if (ret == -1) { perror("epoll_ctl"); exit(1); } struct epoll_event events[MAX_EVENTS]; char buf[BUF_SIZE]; while (1) { int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (num_events == -1) { perror("epoll_wait"); exit(1); } for (int i = 0; i < num_events; i++) { int fd = events[i].data.fd; // 监听socket有新的连接请求 if (fd == listen_sock) { socklen_t client_len = sizeof(client_addr); client_sock = accept(listen_sock, (struct sockaddr*)&client_addr, &client_len); if (client_sock == -1) { perror("accept"); exit(1); } printf("New client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); event.events = EPOLLIN | EPOLLET; event.data.fd = client_sock; ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sock, &event); if (ret == -1) { perror("epoll_ctl"); exit(1); } } // 客户端有数据可读 else { memset(buf, 0, BUF_SIZE); ssize_t recv_size = recv(fd, buf, BUF_SIZE, 0); if (recv_size == -1) { perror("recv"); exit(1); } if (recv_size == 0) { printf("Client disconnected: %d\n", fd); close(fd); continue; } printf("Received data from client: %s\n", buf); // 这里可以对收到的数据进行处理 ssize_t send_size = send(fd, buf, strlen(buf), 0); if (send_size == -1) { perror("send"); exit(1); } } } } close(listen_sock); return 0; }
代码解释
上述代码实现了一个简单的基于epoll的多路复用服务器。程序首先创建一个监听socket,然后绑定和启动监听。之后,程序创建一个epoll实例,并将监听socket添加到epoll实例中,用于监听新的连接请求。
在主循环中,程序调用epoll_wait函数来等待事件的发生。当有事件发生时,程序通过遍历events数组来处理每个事件。如果是监听socket上有新的连接请求,程序调用accept函数接受连接,并将新的客户端socket添加到epoll实例中。
如果是客户端有数据可读,程序调用recv函数读取数据,并对数据进行处理(这部分代码省略了处理逻辑)。然后,程序通过send函数将数据回送给客户端。
总结
通过使用epoll机制,我们可以实现高效且灵活的多路复用。这种方式可以有效地处理大量的并发连接,提高系统的性能。本文提供了一个简单的基于epoll的多路复用服务器示例程序,希望对您理解epoll的工作原理和用法有所帮助。
很赞哦! ()