[user@localhost HomeWork_makefile2]$ make
gcc -Wall -Wextra -std=c99 -o process_server multi_process.c
multi_process.c:54:1: error: stray ‘\346’ in program
void send_http_response(int client_f极, http_status_t status,
^
multi_process.c:54:1: error: stray ‘\236’ in program
multi_process.c:54:1: error: stray ‘\201’ in program
multi_process.c: In function ‘send_http_response’:
multi_process.c:74:10: error: ‘client_fd’ undeclared (first use in this function)
send(client_fd, header, len, 0);
^
multi_process.c:74:10: note: each undeclared identifier is reported only once for each function it appears in
multi_process.c:54:29: warning: unused parameter ‘client_f’ [-Wunused-parameter]
void send_http_response(int client_f极, http_status_t status,
^
multi_process.c: In function ‘send_error_response’:
multi_process.c:80:5: warning: enumeration value ‘HTTP_200’ not handled in switch [-Wswitch]
switch (status) {
^
multi_process.c: In function ‘main’:
multi_process.c:173:22: error: storage size of ‘sa’ isn’t known
struct sigaction sa;
^
multi_process.c:175:5: warning: implicit declaration of function ‘sigemptyset’ [-Wimplicit-function-declaration]
sigemptyset(&sa.sa_mask);
^
multi_process.c:176:19: error: ‘SA_RESTART’ undeclared (first use in this function)
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
^
multi_process.c:176:32: error: ‘SA_NOCLDSTOP’ undeclared (first use in this function)
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
^
multi_process.c:178:5: warning: implicit declaration of function ‘sigaction’ [-Wimplicit-function-declaration]
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
^
multi_process.c:173:22: warning: unused variable ‘sa’ [-Wunused-variable]
struct sigaction sa;
^
makefile:17: recipe for target 'process_server' failed
make: *** [process_server] Error 1 报错如上,代码如下#include "web_server.h"
// 创建socket
int create_socket() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
return sockfd;
}
// 绑定socket
void bind_socket(int sockfd) {
struct sockaddr_in server_addr = {
.sin_family = AF_INET,
.sin_port = htons(PORT),
.sin_addr.s_addr = INADDR_ANY
};
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
close(sockfd);
exit(EXIT_FAILURE);
}
}
// 获取内容类型
const char* get_content_type(const char* path) {
const char* ext = strrchr(path, '.');
if (!ext) return "text/plain";
ext++;
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) return "image/jpeg";
if (strcmp(ext, "png") == 0) return "image/png";
if (strcmp(ext, "gif") == 0) return "image/gif";
if (strcmp(ext, "json") == 0) return "application/json";
return "text/plain";
}
// 检查路径安全性
int is_path_safe(const char* path) {
return strstr(path, "..") == NULL;
}
// 发送HTTP响应
void send_http_response(int client_f极, http_status_t status,
const char* content_type, off_t content_length) {
const char* status_msg = "";
switch (status) {
case HTTP_200: status_msg = "OK"; break;
case HTTP_400: status_msg = "Bad Request"; break;
case HTTP_403: status_msg = "Forbidden"; break;
case HTTP_404: status_msg = "Not Found"; break;
case HTTP_500: status_msg = "Internal Server Error"; break;
case HTTP_501: status_msg = "Not Implemented"; break;
}
char header[512];
int len = snprintf(header, sizeof(header),
"HTTP/1.1 %d %s\r\n"
"Content-Type: %s\r\n"
"Content-Length: %ld\r\n"
"Connection: close\r\n\r\n",
status, status_msg, content_type, content_length);
send(client_fd, header, len, 0);
}
// 发送错误响应
void send_error_response(int client_fd, http_status_t status) {
const char* body = "";
switch (status) {
case HTTP_400: body = "<h1>400 Bad Request</h1>"; break;
case HTTP_403: body = "<h1>403 Forbidden</h1>"; break;
case HTTP_404: body = "<h1>404 Not Found</h1>"; break;
case HTTP_500: body = "<h1>500 Internal Server Error</h1>"; break;
case HTTP_501: body = "<h1>501 Not Implemented</h1>"; break;
}
char response[512];
int len = snprintf(response, sizeof(response),
"HTTP/1.1 %d %s\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %zu\r\n"
"Connection: close\r\n\r\n%s",
status,
(status == 400) ? "Bad Request" :
(status == 403) ? "Forbidden" :
(status == 404) ? "Not Found" :
(status == 500) ? "Internal Server Error" : "Not Implemented",
strlen(body), body);
send(client_fd, response, len, 0);
}
// SIGCHLD信号处理器
void sigchld_handler(int sig) {
(void)sig;
while (waitpid(-1, NULL, WNOHANG) > 0);
}
// 处理客户端请求
void process_request(int client_fd) {
char buffer[MAX_REQUEST_SIZE];
ssize_t bytes_read = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
if (bytes_read <= 0) {
close(client_fd);
exit(EXIT_FAILURE);
}
buffer[bytes_read] = '\0';
char method[16], path[256], protocol[16];
if (sscanf(buffer, "%15s %255s %15s", method, path, protocol) != 3) {
send_error_response(client_fd, HTTP_400);
close(client_fd);
exit(EXIT_FAILURE);
}
if (strcmp(method, "GET") != 0) {
send_error_response(client_fd, HTTP_501);
close(client_fd);
exit(EXIT_FAILURE);
}
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);
exit(EXIT_FAILURE);
}
int file_fd = open(full_path, O_RDONLY);
if (file_fd < 0) {
send_error_response(client_fd, HTTP_404);
close(client_fd);
exit(EXIT_FAILURE);
}
struct stat file_stat;
if (fstat(file_fd, &file_stat) < 0) {
close(file_fd);
send_error_response(client_fd, HTTP_500);
close(client_fd);
exit(EXIT_FAILURE);
}
const char* content_type = get_content_type(full_path);
send_http_response(client_fd, HTTP_200, content_type, file_stat.st_size);
off_t offset = 0;
sendfile(client_fd, file_fd, &offset, file_stat.st_size);
close(file_fd);
close(client_fd);
exit(EXIT_SUCCESS);
}
int main() {
// 设置SIGCHLD处理器
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}
int server_fd = create_socket();
bind_socket(server_fd);
if (listen(server_fd, 128) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("[Process] Web server running on port %d...\n", PORT);
while (1) {
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) {
perror("accept");
continue;
}
pid_t pid = fork();
if (pid == 0) { // 子进程
close(server_fd);
process_request(client_fd);
} else if (pid > 0) { // 父进程
close(client_fd);
} else {
perror("fork");
close(client_fd);
}
}
close(server_fd);
return 0;
}
最新发布