[LinuxServerCode] 对于Epoll et+多线程下ONESHOT字段的作用

博客指出ONESHOT的作用是在任意时刻,让一个socket仅由一个线程处理,这涉及到信息技术中网络编程的相关知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


可以看出ONESHOT的作用就是在任意时刻,一个socket只能由一个线程处理

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/epoll.h> #include <pthread.h> #include <fcntl.h> #define MAX_EVENTS 1024 #define THREAD_POOL_SIZE 4 #define BUFFER_SIZE 4096 #define PORT 8080 // 任务队列结构 typedef struct { void (*task_function)(int); int client_fd; } Task; // 线程池结构 typedef struct { pthread_t *threads; Task *task_queue; int queue_size; int queue_capacity; int head; int tail; int count; pthread_mutex_t lock; pthread_cond_t task_cond; pthread_cond_t space_cond; } ThreadPool; // 全局变量 ThreadPool thread_pool; int epoll_fd; // 设置非阻塞套接字 void set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); } // 初始化线程池 void thread_pool_init(ThreadPool *pool, int size, int capacity) { pool->threads = malloc(size * sizeof(pthread_t)); pool->task_queue = malloc(capacity * sizeof(Task)); pool->queue_size = 0; pool->queue_capacity = capacity; pool->head = 0; pool->tail = 0; pool->count = 0; pthread_mutex_init(&pool->lock, NULL); pthread_cond_init(&pool->task_cond, NULL); pthread_cond_init(&pool->space_cond, NULL); for (int i = 0; i < size; i++) { pthread_create(&pool->threads[i], NULL, (void *)worker_thread, pool); } } // 工作线程函数 void *worker_thread(void *arg) { ThreadPool *pool = (ThreadPool *)arg; while (1) { pthread_mutex_lock(&pool->lock); // 等待任务 while (pool->queue_size == 0) { pthread_cond_wait(&pool->task_cond, &pool->lock); } // 获取任务 Task task = pool->task_queue[pool->head]; pool->head = (pool->head + 1) % pool->queue_capacity; pool->queue_size--; pthread_cond_signal(&pool->space_cond); pthread_mutex_unlock(&pool->lock); // 执行任务 task.task_function(task.client_fd); // 处理完成后重新注册到epoll struct epoll_event event; event.events = EPOLLIN | EPOLLET; event.data.fd = task.client_fd; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, task.client_fd, &event); } return NULL; } // 添加任务到线程池 void add_task(ThreadPool *pool, void (*task_function)(int), int client_fd) { pthread_mutex_lock(&pool->lock); // 等待队列空间 while (pool->queue_size == pool->queue_capacity) { pthread_cond_wait(&pool->space_cond, &pool->lock); } // 添加任务 pool->task_queue[pool->tail].task_function = task_function; pool->task_queue[pool->tail].client_fd = client_fd; pool->tail = (pool->tail + 1) % pool->queue_capacity; pool->queue_size++; pthread_cond_signal(&pool->task_cond); pthread_mutex_unlock(&pool->lock); } // 处理HTTP请求的函数 void handle_request(int client_fd) { char buffer[BUFFER_SIZE]; ssize_t bytes_read = recv(client_fd, buffer, BUFFER_SIZE - 1, 0); if (bytes_read > 0) { buffer[bytes_read] = '\0'; // 简单的HTTP响应 const char *response = "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 31\r\n\r\n" "Hello from C epoll + thread pool!"; send(client_fd, response, strlen(response), 0); } // 注意:实际应用中需要处理Keep-Alive close(client_fd); } int main() { // 创建服务器套接字 int server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd == -1) { perror("socket"); exit(EXIT_FAILURE); } // 设置SO_REUSEADDR int opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // 绑定地址 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("bind"); exit(EXIT_FAILURE); } // 监听 if (listen(server_fd, SOMAXCONN) == -1) { perror("listen"); exit(EXIT_FAILURE); } // 创建epoll实例 epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create1"); exit(EXIT_FAILURE); } // 添加服务器套接字到epoll struct epoll_event event; event.events = EPOLLIN | EPOLLET; event.data.fd = server_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event) == -1) { perror("epoll_ctl: server_fd"); exit(EXIT_FAILURE); } // 初始化线程池 thread_pool_init(&thread_pool, THREAD_POOL_SIZE, 256); // 事件循环 struct epoll_event events[MAX_EVENTS]; printf("Server running on port %d...\n", PORT); while (1) { int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_wait"); exit(EXIT_FAILURE); } for (int i = 0; i < nfds; i++) { // 新连接 if (events[i].data.fd == server_fd) { struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd == -1) { perror("accept"); continue; } // 设置非阻塞 set_nonblocking(client_fd); // 添加到epoll event.events = EPOLLIN | EPOLLET; event.data.fd = client_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event) == -1) { perror("epoll_ctl: client_fd"); close(client_fd); } } // 客户端数据 else if (events[i].events & EPOLLIN) { int client_fd = events[i].data.fd; // 从epoll中暂时移除 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL); // 添加到线程池 add_task(&thread_pool, handle_request, client_fd); } } } close(server_fd); return 0; } 网页加载非常缓慢
最新发布
08-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值