From 1824d1b4d3839e5c39158d1cc1808e905f41d9e9 Mon Sep 17 00:00:00 2001 From: database-mysql Date: Fri, 14 Aug 2026 04:57:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96/=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 50 +++++++++++++++++ CMakeLists.txt | 16 ++++++ index.html | 40 +++++++++++++ main.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++ main_back.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 394 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 index.html create mode 100644 main.c create mode 100644 main_back.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc5a4f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store + +### Other ### +/target +/.idea +/.mvn +/build_release +/upload/ + +### Build Release ### +/cmake-build-debug +./cmake-build-debug diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f645307 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.29) +project(main C) + +set(CMAKE_C_STANDARD 23) + +# 静态链接 +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + +# 或者使用以下方式(更推荐) +add_executable(main main.c) + +if(WIN32) + target_link_libraries(main ws2_32) + # 静态链接所有库 + target_link_options(main PRIVATE -static) +endif() diff --git a/index.html b/index.html new file mode 100644 index 0000000..b01a6d7 --- /dev/null +++ b/index.html @@ -0,0 +1,40 @@ + + + + + + 最小HTTP服务器 + + + +
+

🎉 Hello from C HTTP Server!

+

这是一个用C语言编写的最小HTTP服务器

+

特性:

+ +
+ + diff --git a/main.c b/main.c new file mode 100644 index 0000000..959f426 --- /dev/null +++ b/main.c @@ -0,0 +1,148 @@ +#include +#include +#include + +#ifdef _WIN32 + #include + #include +#else + #include + #include + #include + #include +#endif + +#define PORT 8080 +#define BUFFER_SIZE 1024 +#define HTML_FILE "index.html" + +int main() { +#ifdef _WIN32 + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + perror("WSAStartup failed"); + exit(EXIT_FAILURE); + } + SetConsoleOutputCP(CP_UTF8); +#endif + + int server_fd, new_socket; + struct sockaddr_in address; + int addrlen = sizeof(address); + char buffer[BUFFER_SIZE] = {0}; + + printf("Hello World!\n"); + // 创建socket文件描述符 + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + perror("socket failed"); + exit(EXIT_FAILURE); + } + + // 设置socket选项,允许地址重用 + int opt = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, + (const char *)&opt, sizeof(opt))) { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + + // 配置服务器地址结构 + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(PORT); + + // 绑定socket到指定地址和端口 + if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { + perror("bind failed"); + exit(EXIT_FAILURE); + } + + // 开始监听连接 + if (listen(server_fd, 3) < 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + + printf("HTTP服务器正在监听 %d 端口...\n", PORT); + + while(1) { + if ((new_socket = accept(server_fd, (struct sockaddr *)&address, + &addrlen)) < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + int valread = recv(new_socket, buffer, BUFFER_SIZE, 0); + printf("收到请求:\n%s\n", buffer); + + FILE *html_file = fopen(HTML_FILE, "rb"); + if (!html_file) { + const char *error_response = + "HTTP/1.1 404 Not Found\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Connection: close\r\n" + "\r\n" + "

404 - 文件未找到

"; + send(new_socket, error_response, strlen(error_response), 0); +#ifdef _WIN32 + closesocket(new_socket); +#else + close(new_socket); +#endif + continue; + } + + fseek(html_file, 0, SEEK_END); + long file_size = ftell(html_file); + fseek(html_file, 0, SEEK_SET); + + char *html_content = (char *)malloc(file_size + 1); + if (!html_content) { + fclose(html_file); + const char *error_response = + "HTTP/1.1 500 Internal Server Error\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Connection: close\r\n" + "\r\n" + "

500 - 服务器错误

"; + send(new_socket, error_response, strlen(error_response), 0); +#ifdef _WIN32 + closesocket(new_socket); +#else + close(new_socket); +#endif + continue; + } + + fread(html_content, 1, file_size, html_file); + html_content[file_size] = '\0'; + fclose(html_file); + + char header[512]; + sprintf(header, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Content-Length: %ld\r\n" + "Connection: close\r\n" + "\r\n", file_size); + + send(new_socket, header, strlen(header), 0); + send(new_socket, html_content, file_size, 0); + + free(html_content); + + printf("响应已发送\n"); + +#ifdef _WIN32 + closesocket(new_socket); +#else + close(new_socket); +#endif + } + +#ifdef _WIN32 + WSACleanup(); +#endif + + return 0; +} \ No newline at end of file diff --git a/main_back.c b/main_back.c new file mode 100644 index 0000000..4c996c4 --- /dev/null +++ b/main_back.c @@ -0,0 +1,140 @@ +#include +#include +#include + +#ifdef _WIN32 + #include + #include +#else + #include + #include + #include + #include +#endif + +#define PORT 8080 +#define BUFFER_SIZE 1024 +#define HTML_FILE "index.html" + +int main() { +#ifdef _WIN32 + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + perror("WSAStartup failed"); + exit(EXIT_FAILURE); + } + SetConsoleOutputCP(CP_UTF8); +#endif + + int server_fd, new_socket; + struct sockaddr_in address; + int addrlen = sizeof(address); + char buffer[BUFFER_SIZE] = {0}; + + printf("Hello World!\n"); + // 创建socket文件描述符 + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + perror("socket failed"); + exit(EXIT_FAILURE); + } + + // 设置socket选项,允许地址重用 + int opt = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, + (const char *)&opt, sizeof(opt))) { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + + // 配置服务器地址结构 + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(PORT); + + // 绑定socket到指定地址和端口 + if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { + perror("bind failed"); + exit(EXIT_FAILURE); + } + + // 开始监听连接 + if (listen(server_fd, 3) < 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + + printf("HTTP服务器正在监听 %d 端口...\n", PORT); + + while(1) { + if ((new_socket = accept(server_fd, (struct sockaddr *)&address, + &addrlen)) < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + int valread = recv(new_socket, buffer, BUFFER_SIZE, 0); + printf("收到请求:\n%s\n", buffer); + + FILE *html_file = fopen(HTML_FILE, "rb"); + if (!html_file) { + const char *error_response = + "HTTP/1.1 404 Not Found\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Connection: close\r\n" + "\r\n" + "

404 - 文件未找到

"; + send(new_socket, error_response, strlen(error_response), 0); + closesocket(new_socket); + continue; + } + + fseek(html_file, 0, SEEK_END); + long file_size = ftell(html_file); + fseek(html_file, 0, SEEK_SET); + + char *html_content = (char *)malloc(file_size + 1); + if (!html_content) { + fclose(html_file); + const char *error_response = + "HTTP/1.1 500 Internal Server Error\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Connection: close\r\n" + "\r\n" + "

500 - 服务器错误

"; + send(new_socket, error_response, strlen(error_response), 0); + closesocket(new_socket); + continue; + } + + fread(html_content, 1, file_size, html_file); + html_content[file_size] = '\0'; + fclose(html_file); + + char header[512]; + sprintf(header, + "HTTP/1.1 200 OK\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Content-Length: %ld\r\n" + "Connection: close\r\n" + "\r\n", file_size); + + send(new_socket, header, strlen(header), 0); + send(new_socket, html_content, file_size, 0); + + free(html_content); + + printf("响应已发送\n"); + +#ifdef _WIN32 + closesocket(new_socket); +#else + close(new_socket); +#endif + } + +#ifdef _WIN32 + WSACleanup(); +#endif + + return 0; +} \ No newline at end of file