web服务器,解析并响应get与post请求

“GET 返回页面 + POST 处理数据” 的 Web 服务器

🌐 目标行为

① 浏览器访问网页(GET)

1
GET /

→ 返回 index.html

② HTML 表单提交数据(POST)

1
POST /submit

→ 返回字符串或 JSON

1.创建index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>POST 测试</title>
</head>
<body>
<h1>提交数据测试</h1>

<form action="/submit" method="POST">
<input type="text" name="msg" value="hello from html">
<button type="submit">提交</button>
</form>
</body>
</html>

2.server.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#define _GNU_SOURCE

#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/sendfile.h>


#define PORT 8080

// 解析请求方法
void parse_method(const char *req, char *method) {
sscanf(req, "%7s", method);
}

// 解析路径
void parse_path(const char *req, char *path) {
sscanf(req, "%*s %255s", path);
}

// 获取 Content-Length
int get_content_length(const char *req) {
const char *p = strcasestr(req, "Content-Length:");
if (!p) return 0;
p += strlen("Content-Length:");
while (*p == ' ') p++;
return atoi(p);
}

int main() {
int s = socket(AF_INET, SOCK_STREAM, 0);

int opt = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;

bind(s, (struct sockaddr*)&addr, sizeof(addr));
listen(s, SOMAXCONN);

printf("Server running on http://0.0.0.0:%d\n", PORT);

while (1) {
int client = accept(s, NULL, NULL);

char buffer[4096] = {0};
int received = recv(client, buffer, sizeof(buffer), 0);

if (received <= 0) {
close(client);
continue;
}

char method[8] = {0};
char path[256] = {0};

parse_method(buffer, method);
parse_path(buffer, path);

printf("Method: %s, Path: %s\n", method, path);

// ---------------------------
// 处理 GET /
// ---------------------------
if (strcmp(method, "GET") == 0 && strcmp(path, "/") == 0) {
int fd = open("index.html", O_RDONLY);
if (fd < 0) {
const char *err = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 13\r\n\r\n"
"404 Not Found";
write(client, err, strlen(err));
close(client);
continue;
}

struct stat st;
fstat(fd, &st);

char header[256];
int len = snprintf(header, sizeof(header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %zu\r\n\r\n",
st.st_size
);

write(client, header, len);

off_t offset = 0;
sendfile(client, fd, &offset, st.st_size);

close(fd);
close(client);
continue;
}

// ---------------------------
// 处理 POST /submit
// ---------------------------
if (strcmp(method, "POST") == 0 && strcmp(path, "/submit") == 0) {

int content_length = get_content_length(buffer);

char *body = strstr(buffer, "\r\n\r\n");
if (body) body += 4;

printf("POST body: %.*s\n", content_length, body);

// 返回 JSON
char json[256];
snprintf(json, sizeof(json),
"{\"status\":\"ok\",\"received\":\"%.*s\"}",
content_length, body
);

char header[256];
int len = snprintf(header, sizeof(header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: application/json\r\n"
"Content-Length: %zu\r\n\r\n",
strlen(json)
);

write(client, header, len);
write(client, json, strlen(json));

close(client);
continue;
}

// ---------------------------
// 其他路径 → 404
// ---------------------------
const char *err = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 13\r\n\r\n"
"404 Not Found";
write(client, err, strlen(err));
close(client);
}

close(s);
return 0;
}

3.编译运行

1
2
gcc server.c
./a.out

4.浏览器访问http://127.0.0.1:8080

或者crul命令访问POST请求

1
curl -X POST http://127.0.0.1:8080/submit -d "msg=hello"

5.点击提交表单,查看结果