FD_CLR

从代码可以看出,在set中删除所有和fd相同的项。其中fd是fd_set类型。

#include "web_server.h" #include <sys/select.h> // 创建socket (同多线程版本) int create_socket() { /* 同multithreaded.c */ } void bind_socket(int sockfd) { /* 同multithreaded.c */ } const char* get_content_type(const char* path) { /* 同multithreaded.c */ } int is_path_safe(const char* path) { /* 同multithreaded.c */ } void send_http_response(int client_fd, http_status_t status, const char* content_type, off_t content_length) { /* 同multithreaded.c */ } void send_error_response(int client_fd, http_status_t status) { /* 同multithreaded.c */ } int main() { int server_fd = create_socket(); bind_socket(server_fd); // 设置非阻塞模式 fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_NONBLOCK); if (listen(server_fd, 128) < 0) { perror("listen"); exit(EXIT_FAILURE); } fd_set read_fds, write_fds; FD_ZERO(&read_fds); FD_ZERO(&write_fds); FD_SET(server_fd, &read_fds); int max_fd = server_fd; client_state_t clients[MAX_CLIENTS] = {0}; printf("[IO Multiplex] Web server running on port %d...\n", PORT); while (1) { fd_set tmp_read = read_fds; fd_set tmp_write = write_fds; if (select(max_fd + 1, &tmp_read, &tmp_write, NULL, NULL) < 0) { perror("select"); continue; } // 处理新连接 if (FD_ISSET(server_fd, &tmp_read)) { 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) { fcntl(client_fd, F_SETFL, fcntl(client_fd, F_GETFL) | O_NONBLOCK); // 添加到客户端列表 for (int i = 0; i < MAX_CLIENTS; i++) { if (clients[i].fd == 0) { clients[i].fd = client_fd; clients[i].bytes_received = 0; clients[i].header_sent = 0; FD_SET(client_fd, &read_fds); if (client_fd > max_fd) max_fd = client_fd; break; } } } } // 处理客户端请求 for (int i = 0; i < MAX_CLIENTS; i++) { if (clients[i].fd == 0) continue; int client_fd = clients[i].fd; // 读取数据 if (FD_ISSET(client_fd, &tmp_read)) { ssize_t bytes_read = recv(client_fd, clients[i].request + clients[i].bytes_received, MAX_REQUEST_SIZE - clients[i].bytes_received - 1, 0); if (bytes_read > 0) { clients[i].bytes_received += bytes_read; clients[i].request[clients[i].bytes_received] = '\0'; // 检查完整请求 if (strstr(clients[i].request, "\r\n\r\n")) { char method[16], path[256]; if (sscanf(clients[i].request, "%15s %255s", method, path) == 2 && strcmp(method, "GET") == 0) { char full_path[MAX_PATH_LENGTH]; snprintf(full_path, sizeof(full_path), "%s%s", WEBROOT, (strcmp(path, "/") == 0) ? "/index.html" : path); if (!is_path_safe(full_path)) { send_error_response(client_fd, HTTP_403); close(client_fd); clients[i].fd = 0; FD_CLR(client_fd, &read_fds); FD_CLR(client_fd, &write_fds); continue; } clients[i].file_fd = open(full_path, O_RDONLY); if (clients[i].file_fd < 0) { send_error_response(client_fd, HTTP_404); close(client_fd); clients[i].fd = 0; FD_CLR(client_fd, &read_fds); FD_CLR(client_fd, &write_fds); continue; } struct stat file_stat; fstat(clients[i].file_fd, &file_stat); clients[i].file_size = file_stat.st_size; clients[i].file_offset = 0; const char* content_type = get_content_type(full_path); char header[512]; snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n" "Content-Type: %s\r\n" "Content-Length: %ld\r\n" "Connection: close\r\n\r\n", content_type, clients[i].file_size); memcpy(clients[i].request, header, strlen(header)); clients[i].bytes_received = strlen(header); clients[i].header_sent = 0; FD_CLR(client_fd, &read_fds); FD_SET(client_fd, &write_fds); } else { send_error_response(client_fd, HTTP_400); close(client_fd); clients[i].fd = 0; FD_CLR(client_fd, &read_fds); } } } else if (bytes_read == 0 || (bytes_read < 0 && errno != EAGAIN)) { close(client_fd); if (clients[i].file_fd > 0) close(clients[i].file_fd); clients[i].fd = 0; FD_CLR(client_fd, &read_fds); FD_CLR(client_fd, &write_fds); } } // 发送数据 if (FD_ISSET(client_fd, &tmp_write)) { if (!clients[i].header_sent) { ssize_t bytes_sent = send(client_fd, clients[i].request + clients[i].header_sent, clients[i].bytes_received - clients[i].header_sent, 0); if (bytes_sent > 0) { clients[i].header_sent += bytes_sent; } else if (bytes_sent < 0 && errno != EAGAIN) { close(client_fd); close(clients[i].file_fd); clients[i].fd = 0; FD_CLR(client_fd, &write_fds); continue; } } else { ssize_t bytes_sent = sendfile(client_fd, clients[i].file_fd, &clients[i].file_offset, clients[i].file_size - clients[i].file_offset); if (bytes_sent <= 0 && errno != EAGAIN) { close(client_fd); close(clients[i].file_fd); clients[i].fd = 0; FD_CLR(client_fd, &write_fds); } } } } } close(server_fd); return 0; } 报错代码如下io_multiplex.c: In function ‘bind_socket’: io_multiplex.c:6:22: warning: unused parameter ‘sockfd’ [-Wunused-parameter] void bind_socket(int sockfd) { /* 同multithreaded.c */ } ^ io_multiplex.c: In function ‘get_content_type’: io_multiplex.c:7:42: warning: unused parameter ‘path’ [-Wunused-parameter] const char* get_content_type(const char* path) { /* 同multithreaded.c */ } ^ io_multiplex.c: In function ‘is_path_safe’: io_multiplex.c:8:30: warning: unused parameter ‘path’ [-Wunused-parameter] int is_path_safe(const char* path) { /* 同multithreaded.c */ } ^ io_multiplex.c: In function ‘send_http_response’: io_multiplex.c:9:29: warning: unused parameter ‘client_fd’ [-Wunused-parameter] void send_http_response(int client_fd, http_status_t status, ^ io_multiplex.c:9:54: warning: unused parameter ‘status’ [-Wunused-parameter] void send_http_response(int client_fd, http_status_t status, ^ io_multiplex.c:10:37: warning: unused parameter ‘content_type’ [-Wunused-parameter] const char* content_type, off_t content_length) { /* 同multithreaded.c */ } ^ io_multiplex.c:10:57: warning: unused parameter ‘content_length’ [-Wunused-parameter] const char* content_type, off_t content_length) { /* 同multithreaded.c */ } ^ io_multiplex.c: In function ‘send_error_response’: io_multiplex.c:11:30: warning: unused parameter ‘client_fd’ [-Wunused-parameter] void send_error_response(int client_fd, http_status_t status) { /* 同multithreaded.c */ } ^ io_multiplex.c:11:55: warning: unused parameter ‘status’ [-Wunused-parameter] void send_error_response(int client_fd, http_status_t status) { /* 同multithreaded.c */ } ^ io_multiplex.c: In function ‘main’: io_multiplex.c:31:5: warning: missing braces around initializer [-Wmissing-braces] client_state_t clients[MAX_CLIENTS] = {0}; ^ io_multiplex.c:31:5: warning: (near initialization for ‘clients[0]’) [-Wmissing-braces] io_multiplex.c: In function ‘create_socket’: io_multiplex.c:5:1: warning: control reaches end of non-void function [-Wreturn-type] int create_socket() { /* 同multithreaded.c */ } ^ io_multiplex.c: In function ‘get_content_type’: io_multiplex.c:7:1: warning: control reaches end of non-void function [-Wreturn-type] const char* get_content_type(const char* path) { /* 同multithreaded.c */ } ^ io_multiplex.c: In function ‘is_path_safe’: io_multiplex.c:8:1: warning: control reaches end of non-void function [-Wreturn-type] int is_path_safe(const char* path) { /* 同multithreaded.c */ } ^
最新发布
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值