这是一个给函数添加注释的模板,按照该模板给代码中的函数添加函数注释:/*
* fn int bulk_mem_copy(unsigned char *to, unsigned char *from, int len)
* brief 安全的内存复制函数,支持重叠内存区域和高效字长复制
* details
*
* param[in] to - 目标内存地址指针
* param[in] from - 源内存地址指针
* param[in] len - 复制字节数
* param[out]
*
* return 复制结果 0 表示成功,-1 表示参数无效
*/
需要添加注释的代码:#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#define PORT 80
#define WEB_ROOT “./web”
#define BUFFER_SIZE 4096
#define MAX_EVENTS 10000
#define MAX_THREADS 100
#define MAX_PROCESSES 10
// 全局配置
typedef struct {
int mode; // 0:epoll, 1:thread, 2:process
int debug;
} ServerConfig;
// HTTP响应模板
const char* http_200 =
“HTTP/1.1 200 OK\r\n”
“Content-Type: %s\r\n”
“Connection: close\r\n\r\n”;
const char* http_404 =
“HTTP/1.1 404 Not Found\r\n”
“Content-Type: text/html\r\n”
“Connection: close\r\n\r\n”
“
404 Not Found”;
const char* http_400 =
“HTTP/1.1 400 Bad Request\r\n”
“Content-Type: text/html\r\n”
“Connection: close\r\n\r\n”
“
400 Bad Request”;
// 调试输出
void debug_print(ServerConfig config, const char* format, …) {
if (!config.debug) return;
va_list args; va_start(args, format); vprintf(format, args); va_end(args); fflush(stdout);
}
// 获取文件MIME类型
const char* get_mime_type(const char* path) {
const char *ext = strrchr(path, ‘.’);
if (!ext) return “text/plain”;
if (strcmp(ext, ".html") == 0) return "text/html"; if (strcmp(ext, ".css") == 0) return "text/css"; if (strcmp(ext, ".js") == 0) return "application/javascript"; if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return "image/jpeg"; if (strcmp(ext, ".png") == 0) return "image/png"; if (strcmp(ext, ".gif") == 0) return "image/gif"; return "text/plain";
}
// 发送文件内容
void send_file(int client_fd, const char* filepath) {
int fd = open(filepath, O_RDONLY);
if (fd < 0) {
write(client_fd, http_404, strlen(http_404));
return;
}
// 获取文件信息 struct stat st; fstat(fd, &st); off_t file_size = st.st_size; // 构建响应头 char header[BUFFER_SIZE]; const char* mime_type = get_mime_type(filepath); snprintf(header, sizeof(header), http_200, mime_type); write(client_fd, header, strlen(header)); // 零拷贝发送文件 off_t offset = 0; while (offset < file_size) { ssize_t sent = sendfile(client_fd, fd, &offset, file_size - offset); if (sent <= 0) break; } close(fd);
}
// 处理客户端请求
void handle_request(int client_fd, ServerConfig config) {
char buffer[BUFFER_SIZE];
ssize_t bytes_read = read(client_fd, buffer, BUFFER_SIZE - 1);
if (bytes_read <= 0) { close(client_fd); return; } buffer[bytes_read] = '\0'; debug_print(config, "Received request:\n%s\n", buffer); // 解析请求行 char method[16], path[256], protocol[16]; if (sscanf(buffer, "%15s %255s %15s", method, path, protocol) != 3) { write(client_fd, http_400, strlen(http_400)); close(client_fd); return; } // 安全处理:防止路径遍历攻击 if (strstr(path, "..")) { write(client_fd, http_404, strlen(http_404)); close(client_fd); return; } // 默认页面处理 if (strcmp(path, "/") == 0) { strcpy(path, "/index.html"); } char fullpath[512]; snprintf(fullpath, sizeof(fullpath), "%s%s", WEB_ROOT, path); if (strcmp(method, "GET") == 0) { send_file(client_fd, fullpath); } else if (strcmp(method, "POST") == 0) { // 查找请求体 char* body = strstr(buffer, "\r\n\r\n"); if (body) body += 4; else body = ""; char response[BUFFER_SIZE]; snprintf(response, sizeof(response), "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n" "Connection: close\r\n\r\n" "<html><body><h1>Received: %s</h1></body></html>", body); write(client_fd, response, strlen(response)); } else { write(client_fd, http_400, strlen(http_400)); } close(client_fd);
}
// ================== 多线程模式 ==================
typedef struct {
int client_fd;
ServerConfig config;
} ThreadArgs;
void* thread_handler(void* arg) {
ThreadArgs* args = (ThreadArgs*)arg;
handle_request(args->client_fd, args->config);
free(args);
return NULL;
}
void run_multithread_server(ServerConfig config) {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
perror(“socket”);
exit(EXIT_FAILURE);
}
// 端口复用 int opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, .sin_port = htons(PORT) }; if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); close(server_fd); exit(EXIT_FAILURE); } if (listen(server_fd, 10000) < 0) { perror("listen"); close(server_fd); exit(EXIT_FAILURE); } printf("Multithread server running on port %d\n", PORT); while (1) { int client_fd = accept(server_fd, NULL, NULL); if (client_fd < 0) { perror("accept"); continue; } ThreadArgs* args = malloc(sizeof(ThreadArgs)); args->client_fd = client_fd; args->config = config; pthread_t thread; if (pthread_create(&thread, NULL, thread_handler, args) != 0) { perror("pthread_create"); close(client_fd); free(args); } else { pthread_detach(thread); } }
}
// ================== 多进程模式 ==================
void run_multiprocess_server(ServerConfig config) {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
perror(“socket”);
exit(EXIT_FAILURE);
}
// 端口复用 int opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, .sin_port = htons(PORT) }; if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); close(server_fd); exit(EXIT_FAILURE); } if (listen(server_fd, 10000) < 0) { perror("listen"); close(server_fd); exit(EXIT_FAILURE); } printf("Multiprocess server running on port %d\n", PORT); // 防止僵尸进程 signal(SIGCHLD, SIG_IGN); while (1) { int client_fd = accept(server_fd, NULL, NULL); if (client_fd < 0) { perror("accept"); continue; } pid_t pid = fork(); if (pid == 0) { // 子进程 close(server_fd); handle_request(client_fd, config); exit(0); } else if (pid > 0) { // 父进程 close(client_fd); } else { perror("fork"); close(client_fd); } }
}
// ================== Epoll模式 ==================
void run_epoll_server(ServerConfig config) {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
perror(“socket”);
exit(EXIT_FAILURE);
}
// 设置非阻塞和端口复用 fcntl(server_fd, F_SETFL, O_NONBLOCK); int opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, .sin_port = htons(PORT) }; if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); close(server_fd); exit(EXIT_FAILURE); } if (listen(server_fd, 10000) < 0) { perror("listen"); close(server_fd); exit(EXIT_FAILURE); } printf("Epoll server running on port %d\n", PORT); // 创建epoll实例 int epoll_fd = epoll_create1(0); if (epoll_fd < 0) { perror("epoll_create1"); close(server_fd); exit(EXIT_FAILURE); } struct epoll_event event = { .events = EPOLLIN, .data.fd = server_fd }; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event) < 0) { perror("epoll_ctl"); close(server_fd); close(epoll_fd); exit(EXIT_FAILURE); } struct epoll_event events[MAX_EVENTS]; while (1) { int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (n < 0) { perror("epoll_wait"); continue; } for (int i = 0; i < n; i++) { if (events[i].data.fd == server_fd) { // 处理新连接 struct sockaddr_in client_addr; socklen_t addr_len = sizeof(client_addr); int client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len); if (client_fd < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { perror("accept"); } continue; } fcntl(client_fd, F_SETFL, O_NONBLOCK); struct epoll_event client_event = { .events = EPOLLIN | EPOLLET, // 边缘触发模式 .data.fd = client_fd }; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &client_event) < 0) { perror("epoll_ctl"); close(client_fd); } } else { // 处理客户端请求 handle_request(events[i].data.fd, config); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL); } } }
}
int main(int argc, char* argv[]) {
ServerConfig config = {0};
config.debug = 1; // 默认开启调试
// 解析命令行参数 if (argc < 2) { printf("Usage: %s [--epoll | --thread | --process] [--debug]\n", argv[0]); return 1; } for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--epoll") == 0) config.mode = 0; else if (strcmp(argv[i], "--thread") == 0) config.mode = 1; else if (strcmp(argv[i], "--process") == 0) config.mode = 2; else if (strcmp(argv[i], "--debug") == 0) config.debug = 1; else if (strcmp(argv[i], "--no-debug") == 0) config.debug = 0; } // 根据模式启动服务器 switch (config.mode) { case 0: // epoll run_epoll_server(config); break; case 1: // thread run_multithread_server(config); break; case 2: // process run_multiprocess_server(config); break; default: printf("Invalid mode\n"); return 1; } return 0;
}