初始化/推送
This commit is contained in:
50
.gitignore
vendored
Normal file
50
.gitignore
vendored
Normal file
@@ -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
|
||||||
16
CMakeLists.txt
Normal file
16
CMakeLists.txt
Normal file
@@ -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()
|
||||||
40
index.html
Normal file
40
index.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>最小HTTP服务器</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="info">
|
||||||
|
<h1>🎉 Hello from C HTTP Server!</h1>
|
||||||
|
<p>这是一个用C语言编写的最小HTTP服务器</p>
|
||||||
|
<p><strong>特性:</strong></p>
|
||||||
|
<ul>
|
||||||
|
<li>使用原生Socket API</li>
|
||||||
|
<li>支持Windows、Linux平台</li>
|
||||||
|
<li>从文件读取HTML内容</li>
|
||||||
|
<li>正确处理UTF-8编码</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
148
main.c
Normal file
148
main.c
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#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"
|
||||||
|
"<html><body><h1>404 - 文件未找到</h1></body></html>";
|
||||||
|
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"
|
||||||
|
"<html><body><h1>500 - 服务器错误</h1></body></html>";
|
||||||
|
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;
|
||||||
|
}
|
||||||
140
main_back.c
Normal file
140
main_back.c
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#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"
|
||||||
|
"<html><body><h1>404 - 文件未找到</h1></body></html>";
|
||||||
|
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"
|
||||||
|
"<html><body><h1>500 - 服务器错误</h1></body></html>";
|
||||||
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user