#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;
}
网页加载非常缓慢
最新发布