C语言应用场景:网络编程

C语言在网络编程领域具有独特优势,其高效的性能、精确的内存控制和丰富的系统调用接口,使其成为开发高性能网络应用的首选语言。从底层Socket编程到高级网络服务器,C语言都能提供强大的支持。

1. Socket编程基础

1.1 Socket基本概念

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include <netdb.h>

// Socket类型定义
typedef enum {
SOCKET_TYPE_TCP = SOCK_STREAM,
SOCKET_TYPE_UDP = SOCK_DGRAM,
SOCKET_TYPE_RAW = SOCK_RAW
} socket_type_t;

// Socket状态
typedef enum {
SOCKET_STATE_CLOSED = 0,
SOCKET_STATE_LISTENING,
SOCKET_STATE_CONNECTING,
SOCKET_STATE_CONNECTED,
SOCKET_STATE_ERROR
} socket_state_t;

// Socket信息结构
typedef struct {
int fd; // 文件描述符
socket_type_t type; // Socket类型
socket_state_t state; // Socket状态
struct sockaddr_in local_addr; // 本地地址
struct sockaddr_in remote_addr; // 远程地址
int reuse_addr; // 地址重用
int non_blocking; // 非阻塞模式
int keep_alive; // 保持连接
int send_buffer_size; // 发送缓冲区大小
int recv_buffer_size; // 接收缓冲区大小
time_t create_time; // 创建时间
time_t last_activity; // 最后活动时间
} socket_info_t;

// 创建Socket
socket_info_t* create_socket(socket_type_t type, const char* ip, int port) {
socket_info_t* sock_info = (socket_info_t*)malloc(sizeof(socket_info_t));
if (!sock_info) {
printf("错误: 无法分配Socket信息内存\n");
return NULL;
}

memset(sock_info, 0, sizeof(socket_info_t));

// 创建Socket
sock_info->fd = socket(AF_INET, type, 0);
if (sock_info->fd < 0) {
printf("错误: 创建Socket失败: %s\n", strerror(errno));
free(sock_info);
return NULL;
}

sock_info->type = type;
sock_info->state = SOCKET_STATE_CLOSED;
sock_info->create_time = time(NULL);
sock_info->last_activity = sock_info->create_time;

// 设置本地地址
sock_info->local_addr.sin_family = AF_INET;
sock_info->local_addr.sin_port = htons(port);
if (ip && strlen(ip) > 0) {
inet_pton(AF_INET, ip, &sock_info->local_addr.sin_addr);
} else {
sock_info->local_addr.sin_addr.s_addr = INADDR_ANY;
}

printf("创建Socket: fd=%d, 类型=%s, 地址=%s:%d\n",
sock_info->fd,
(type == SOCKET_TYPE_TCP) ? "TCP" : "UDP",
ip ? ip : "0.0.0.0", port);

return sock_info;
}

// 设置Socket选项
int set_socket_option(socket_info_t* sock_info, int option, int value) {
if (!sock_info || sock_info->fd < 0) {
return -1;
}

int result = 0;

switch (option) {
case SO_REUSEADDR:
result = setsockopt(sock_info->fd, SOL_SOCKET, SO_REUSEADDR,
&value, sizeof(value));
if (result == 0) {
sock_info->reuse_addr = value;
}
break;

case SO_KEEPALIVE:
result = setsockopt(sock_info->fd, SOL_SOCKET, SO_KEEPALIVE,
&value, sizeof(value));
if (result == 0) {
sock_info->keep_alive = value;
}
break;

case SO_SNDBUF:
result = setsockopt(sock_info->fd, SOL_SOCKET, SO_SNDBUF,
&value, sizeof(value));
if (result == 0) {
sock_info->send_buffer_size = value;
}
break;

case SO_RCVBUF:
result = setsockopt(sock_info->fd, SOL_SOCKET, SO_RCVBUF,
&value, sizeof(value));
if (result == 0) {
sock_info->recv_buffer_size = value;
}
break;

default:
result = setsockopt(sock_info->fd, SOL_SOCKET, option,
&value, sizeof(value));
break;
}

if (result < 0) {
printf("错误: 设置Socket选项失败: %s\n", strerror(errno));
} else {
printf("设置Socket选项: fd=%d, 选项=%d, 值=%d\n",
sock_info->fd, option, value);
}

return result;
}

// 设置非阻塞模式
int set_non_blocking(socket_info_t* sock_info, int non_blocking) {
if (!sock_info || sock_info->fd < 0) {
return -1;
}

int flags = fcntl(sock_info->fd, F_GETFL, 0);
if (flags < 0) {
printf("错误: 获取Socket标志失败: %s\n", strerror(errno));
return -1;
}

if (non_blocking) {
flags |= O_NONBLOCK;
} else {
flags &= ~O_NONBLOCK;
}

if (fcntl(sock_info->fd, F_SETFL, flags) < 0) {
printf("错误: 设置Socket标志失败: %s\n", strerror(errno));
return -1;
}

sock_info->non_blocking = non_blocking;
printf("设置Socket模式: fd=%d, 非阻塞=%s\n",
sock_info->fd, non_blocking ? "是" : "否");

return 0;
}

// 绑定Socket
int bind_socket(socket_info_t* sock_info) {
if (!sock_info || sock_info->fd < 0) {
return -1;
}

if (bind(sock_info->fd, (struct sockaddr*)&sock_info->local_addr,
sizeof(sock_info->local_addr)) < 0) {
printf("错误: 绑定Socket失败: %s\n", strerror(errno));
return -1;
}

char ip_str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &sock_info->local_addr.sin_addr, ip_str, sizeof(ip_str));

printf("绑定Socket: fd=%d, 地址=%s:%d\n",
sock_info->fd, ip_str, ntohs(sock_info->local_addr.sin_port));

return 0;
}

// 监听Socket
int listen_socket(socket_info_t* sock_info, int backlog) {
if (!sock_info || sock_info->fd < 0) {
return -1;
}

if (sock_info->type != SOCKET_TYPE_TCP) {
printf("错误: 只有TCP Socket可以监听\n");
return -1;
}

if (listen(sock_info->fd, backlog) < 0) {
printf("错误: 监听Socket失败: %s\n", strerror(errno));
return -1;
}

sock_info->state = SOCKET_STATE_LISTENING;

printf("监听Socket: fd=%d, 队列长度=%d\n", sock_info->fd, backlog);

return 0;
}

// 连接Socket
int connect_socket(socket_info_t* sock_info, const char* ip, int port) {
if (!sock_info || sock_info->fd < 0) {
return -1;
}

// 设置远程地址
sock_info->remote_addr.sin_family = AF_INET;
sock_info->remote_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &sock_info->remote_addr.sin_addr) <= 0) {
printf("错误: 无效的IP地址: %s\n", ip);
return -1;
}

sock_info->state = SOCKET_STATE_CONNECTING;

if (connect(sock_info->fd, (struct sockaddr*)&sock_info->remote_addr,
sizeof(sock_info->remote_addr)) < 0) {
if (errno == EINPROGRESS && sock_info->non_blocking) {
printf("连接进行中: fd=%d, 地址=%s:%d\n", sock_info->fd, ip, port);
return 0; // 非阻塞连接进行中
} else {
printf("错误: 连接Socket失败: %s\n", strerror(errno));
sock_info->state = SOCKET_STATE_ERROR;
return -1;
}
}

sock_info->state = SOCKET_STATE_CONNECTED;
sock_info->last_activity = time(NULL);

printf("连接成功: fd=%d, 地址=%s:%d\n", sock_info->fd, ip, port);

return 0;
}

// 接受连接
socket_info_t* accept_socket(socket_info_t* listen_sock) {
if (!listen_sock || listen_sock->fd < 0 ||
listen_sock->state != SOCKET_STATE_LISTENING) {
return NULL;
}

struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);

int client_fd = accept(listen_sock->fd, (struct sockaddr*)&client_addr, &addr_len);
if (client_fd < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
printf("错误: 接受连接失败: %s\n", strerror(errno));
}
return NULL;
}

// 创建客户端Socket信息
socket_info_t* client_sock = (socket_info_t*)malloc(sizeof(socket_info_t));
if (!client_sock) {
close(client_fd);
return NULL;
}

memset(client_sock, 0, sizeof(socket_info_t));
client_sock->fd = client_fd;
client_sock->type = SOCKET_TYPE_TCP;
client_sock->state = SOCKET_STATE_CONNECTED;
client_sock->local_addr = listen_sock->local_addr;
client_sock->remote_addr = client_addr;
client_sock->create_time = time(NULL);
client_sock->last_activity = client_sock->create_time;

char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip));

printf("接受连接: fd=%d, 客户端=%s:%d\n",
client_fd, client_ip, ntohs(client_addr.sin_port));

return client_sock;
}

// 发送数据
ssize_t send_data(socket_info_t* sock_info, const void* data, size_t len, int flags) {
if (!sock_info || sock_info->fd < 0 || !data) {
return -1;
}

ssize_t sent = send(sock_info->fd, data, len, flags);

if (sent < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
printf("错误: 发送数据失败: %s\n", strerror(errno));
sock_info->state = SOCKET_STATE_ERROR;
}
} else {
sock_info->last_activity = time(NULL);
printf("发送数据: fd=%d, 长度=%zd/%zu\n", sock_info->fd, sent, len);
}

return sent;
}

// 接收数据
ssize_t recv_data(socket_info_t* sock_info, void* buffer, size_t len, int flags) {
if (!sock_info || sock_info->fd < 0 || !buffer) {
return -1;
}

ssize_t received = recv(sock_info->fd, buffer, len, flags);

if (received < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
printf("错误: 接收数据失败: %s\n", strerror(errno));
sock_info->state = SOCKET_STATE_ERROR;
}
} else if (received == 0) {
printf("连接关闭: fd=%d\n", sock_info->fd);
sock_info->state = SOCKET_STATE_CLOSED;
} else {
sock_info->last_activity = time(NULL);
printf("接收数据: fd=%d, 长度=%zd\n", sock_info->fd, received);
}

return received;
}

// UDP发送数据
ssize_t sendto_data(socket_info_t* sock_info, const void* data, size_t len,
const char* ip, int port) {
if (!sock_info || sock_info->fd < 0 || !data) {
return -1;
}

struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &dest_addr.sin_addr) <= 0) {
printf("错误: 无效的IP地址: %s\n", ip);
return -1;
}

ssize_t sent = sendto(sock_info->fd, data, len, 0,
(struct sockaddr*)&dest_addr, sizeof(dest_addr));

if (sent < 0) {
printf("错误: UDP发送失败: %s\n", strerror(errno));
} else {
sock_info->last_activity = time(NULL);
printf("UDP发送: fd=%d, 目标=%s:%d, 长度=%zd\n",
sock_info->fd, ip, port, sent);
}

return sent;
}

// UDP接收数据
ssize_t recvfrom_data(socket_info_t* sock_info, void* buffer, size_t len,
char* src_ip, int* src_port) {
if (!sock_info || sock_info->fd < 0 || !buffer) {
return -1;
}

struct sockaddr_in src_addr;
socklen_t addr_len = sizeof(src_addr);

ssize_t received = recvfrom(sock_info->fd, buffer, len, 0,
(struct sockaddr*)&src_addr, &addr_len);

if (received < 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
printf("错误: UDP接收失败: %s\n", strerror(errno));
}
} else {
sock_info->last_activity = time(NULL);

if (src_ip) {
inet_ntop(AF_INET, &src_addr.sin_addr, src_ip, INET_ADDRSTRLEN);
}
if (src_port) {
*src_port = ntohs(src_addr.sin_port);
}

printf("UDP接收: fd=%d, 来源=%s:%d, 长度=%zd\n",
sock_info->fd,
src_ip ? src_ip : "unknown",
src_port ? *src_port : 0,
received);
}

return received;
}

// 关闭Socket
void close_socket(socket_info_t* sock_info) {
if (!sock_info) {
return;
}

if (sock_info->fd >= 0) {
close(sock_info->fd);
printf("关闭Socket: fd=%d\n", sock_info->fd);
}

free(sock_info);
}

// Socket信息打印
void print_socket_info(const socket_info_t* sock_info) {
if (!sock_info) {
return;
}

char local_ip[INET_ADDRSTRLEN];
char remote_ip[INET_ADDRSTRLEN];

inet_ntop(AF_INET, &sock_info->local_addr.sin_addr, local_ip, sizeof(local_ip));
inet_ntop(AF_INET, &sock_info->remote_addr.sin_addr, remote_ip, sizeof(remote_ip));

printf("Socket信息:\n");
printf(" 文件描述符: %d\n", sock_info->fd);
printf(" 类型: %s\n", (sock_info->type == SOCKET_TYPE_TCP) ? "TCP" : "UDP");
printf(" 状态: %d\n", sock_info->state);
printf(" 本地地址: %s:%d\n", local_ip, ntohs(sock_info->local_addr.sin_port));
printf(" 远程地址: %s:%d\n", remote_ip, ntohs(sock_info->remote_addr.sin_port));
printf(" 非阻塞: %s\n", sock_info->non_blocking ? "是" : "否");
printf(" 地址重用: %s\n", sock_info->reuse_addr ? "是" : "否");
printf(" 保持连接: %s\n", sock_info->keep_alive ? "是" : "否");
printf(" 发送缓冲区: %d\n", sock_info->send_buffer_size);
printf(" 接收缓冲区: %d\n", sock_info->recv_buffer_size);
printf(" 创建时间: %ld\n", sock_info->create_time);
printf(" 最后活动: %ld\n", sock_info->last_activity);
}

1.2 基本Socket示例

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
// TCP客户端示例
void tcp_client_example(void) {
printf("=== TCP客户端示例 ===\n");

// 创建TCP Socket
socket_info_t* client = create_socket(SOCKET_TYPE_TCP, NULL, 0);
if (!client) {
return;
}

// 连接到服务器
if (connect_socket(client, "127.0.0.1", 8080) < 0) {
close_socket(client);
return;
}

// 发送数据
const char* message = "Hello, Server!";
if (send_data(client, message, strlen(message), 0) < 0) {
close_socket(client);
return;
}

// 接收响应
char buffer[1024];
ssize_t received = recv_data(client, buffer, sizeof(buffer) - 1, 0);
if (received > 0) {
buffer[received] = '\0';
printf("服务器响应: %s\n", buffer);
}

close_socket(client);
}

// TCP服务器示例
void tcp_server_example(void) {
printf("=== TCP服务器示例 ===\n");

// 创建TCP Socket
socket_info_t* server = create_socket(SOCKET_TYPE_TCP, "0.0.0.0", 8080);
if (!server) {
return;
}

// 设置地址重用
set_socket_option(server, SO_REUSEADDR, 1);

// 绑定地址
if (bind_socket(server) < 0) {
close_socket(server);
return;
}

// 开始监听
if (listen_socket(server, 10) < 0) {
close_socket(server);
return;
}

printf("服务器启动,等待连接...\n");

// 接受连接
socket_info_t* client = accept_socket(server);
if (client) {
// 接收数据
char buffer[1024];
ssize_t received = recv_data(client, buffer, sizeof(buffer) - 1, 0);
if (received > 0) {
buffer[received] = '\0';
printf("客户端消息: %s\n", buffer);

// 发送响应
const char* response = "Hello, Client!";
send_data(client, response, strlen(response), 0);
}

close_socket(client);
}

close_socket(server);
}

// UDP示例
void udp_example(void) {
printf("=== UDP示例 ===\n");

// 创建UDP Socket
socket_info_t* udp_sock = create_socket(SOCKET_TYPE_UDP, "0.0.0.0", 9090);
if (!udp_sock) {
return;
}

// 绑定地址
if (bind_socket(udp_sock) < 0) {
close_socket(udp_sock);
return;
}

// 发送UDP数据
const char* message = "UDP Message";
sendto_data(udp_sock, message, strlen(message), "127.0.0.1", 9090);

// 接收UDP数据
char buffer[1024];
char src_ip[INET_ADDRSTRLEN];
int src_port;

ssize_t received = recvfrom_data(udp_sock, buffer, sizeof(buffer) - 1,
src_ip, &src_port);
if (received > 0) {
buffer[received] = '\0';
printf("UDP消息: %s (来自 %s:%d)\n", buffer, src_ip, src_port);
}

close_socket(udp_sock);
}

2. I/O多路复用

2.1 Select模型

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#include <sys/select.h>
#include <sys/time.h>

// Select事件类型
typedef enum {
SELECT_EVENT_READ = 1,
SELECT_EVENT_WRITE = 2,
SELECT_EVENT_ERROR = 4
} select_event_t;

// Select管理器
typedef struct {
fd_set read_fds;
fd_set write_fds;
fd_set error_fds;
fd_set master_read_fds;
fd_set master_write_fds;
fd_set master_error_fds;
int max_fd;
socket_info_t* sockets[FD_SETSIZE];
int socket_count;
} select_manager_t;

// 初始化Select管理器
select_manager_t* select_manager_init(void) {
select_manager_t* manager = (select_manager_t*)malloc(sizeof(select_manager_t));
if (!manager) {
return NULL;
}

FD_ZERO(&manager->master_read_fds);
FD_ZERO(&manager->master_write_fds);
FD_ZERO(&manager->master_error_fds);

manager->max_fd = -1;
manager->socket_count = 0;

memset(manager->sockets, 0, sizeof(manager->sockets));

printf("初始化Select管理器\n");

return manager;
}

// 添加Socket到Select管理器
int select_add_socket(select_manager_t* manager, socket_info_t* sock_info,
int events) {
if (!manager || !sock_info || sock_info->fd < 0 || sock_info->fd >= FD_SETSIZE) {
return -1;
}

manager->sockets[sock_info->fd] = sock_info;

if (events & SELECT_EVENT_READ) {
FD_SET(sock_info->fd, &manager->master_read_fds);
}
if (events & SELECT_EVENT_WRITE) {
FD_SET(sock_info->fd, &manager->master_write_fds);
}
if (events & SELECT_EVENT_ERROR) {
FD_SET(sock_info->fd, &manager->master_error_fds);
}

if (sock_info->fd > manager->max_fd) {
manager->max_fd = sock_info->fd;
}

manager->socket_count++;

printf("添加Socket到Select: fd=%d, 事件=0x%x\n", sock_info->fd, events);

return 0;
}

// 从Select管理器移除Socket
int select_remove_socket(select_manager_t* manager, socket_info_t* sock_info) {
if (!manager || !sock_info || sock_info->fd < 0) {
return -1;
}

FD_CLR(sock_info->fd, &manager->master_read_fds);
FD_CLR(sock_info->fd, &manager->master_write_fds);
FD_CLR(sock_info->fd, &manager->master_error_fds);

manager->sockets[sock_info->fd] = NULL;
manager->socket_count--;

// 重新计算max_fd
if (sock_info->fd == manager->max_fd) {
manager->max_fd = -1;
for (int i = 0; i < FD_SETSIZE; i++) {
if (manager->sockets[i] && i > manager->max_fd) {
manager->max_fd = i;
}
}
}

printf("从Select移除Socket: fd=%d\n", sock_info->fd);

return 0;
}

// Select等待事件
int select_wait(select_manager_t* manager, int timeout_ms) {
if (!manager) {
return -1;
}

// 复制fd_set
manager->read_fds = manager->master_read_fds;
manager->write_fds = manager->master_write_fds;
manager->error_fds = manager->master_error_fds;

struct timeval timeout;
struct timeval* timeout_ptr = NULL;

if (timeout_ms >= 0) {
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
timeout_ptr = &timeout;
}

int ready = select(manager->max_fd + 1, &manager->read_fds,
&manager->write_fds, &manager->error_fds, timeout_ptr);

if (ready < 0) {
printf("错误: Select失败: %s\n", strerror(errno));
} else if (ready == 0) {
printf("Select超时\n");
} else {
printf("Select就绪: %d个事件\n", ready);
}

return ready;
}

// 检查Socket事件
int select_check_events(select_manager_t* manager, socket_info_t* sock_info) {
if (!manager || !sock_info || sock_info->fd < 0) {
return 0;
}

int events = 0;

if (FD_ISSET(sock_info->fd, &manager->read_fds)) {
events |= SELECT_EVENT_READ;
}
if (FD_ISSET(sock_info->fd, &manager->write_fds)) {
events |= SELECT_EVENT_WRITE;
}
if (FD_ISSET(sock_info->fd, &manager->error_fds)) {
events |= SELECT_EVENT_ERROR;
}

return events;
}

// Select服务器示例
void select_server_example(void) {
printf("=== Select服务器示例 ===\n");

// 创建Select管理器
select_manager_t* manager = select_manager_init();
if (!manager) {
return;
}

// 创建监听Socket
socket_info_t* listen_sock = create_socket(SOCKET_TYPE_TCP, "0.0.0.0", 8080);
if (!listen_sock) {
free(manager);
return;
}

set_socket_option(listen_sock, SO_REUSEADDR, 1);

if (bind_socket(listen_sock) < 0 || listen_socket(listen_sock, 10) < 0) {
close_socket(listen_sock);
free(manager);
return;
}

// 添加监听Socket到Select
select_add_socket(manager, listen_sock, SELECT_EVENT_READ);

printf("Select服务器启动,等待连接...\n");

// 主循环
for (int i = 0; i < 10; i++) { // 限制循环次数用于演示
int ready = select_wait(manager, 5000); // 5秒超时

if (ready <= 0) {
continue;
}

// 检查监听Socket
if (select_check_events(manager, listen_sock) & SELECT_EVENT_READ) {
socket_info_t* client = accept_socket(listen_sock);
if (client) {
set_non_blocking(client, 1);
select_add_socket(manager, client, SELECT_EVENT_READ);
}
}

// 检查客户端Socket
for (int fd = 0; fd <= manager->max_fd; fd++) {
socket_info_t* sock = manager->sockets[fd];
if (!sock || sock == listen_sock) {
continue;
}

int events = select_check_events(manager, sock);

if (events & SELECT_EVENT_READ) {
char buffer[1024];
ssize_t received = recv_data(sock, buffer, sizeof(buffer) - 1, 0);

if (received > 0) {
buffer[received] = '\0';
printf("客户端消息: %s\n", buffer);

// 回显消息
send_data(sock, buffer, received, 0);
} else if (received == 0 || sock->state == SOCKET_STATE_ERROR) {
// 连接关闭或错误
select_remove_socket(manager, sock);
close_socket(sock);
}
}

if (events & SELECT_EVENT_ERROR) {
printf("Socket错误: fd=%d\n", sock->fd);
select_remove_socket(manager, sock);
close_socket(sock);
}
}
}

// 清理资源
for (int fd = 0; fd <= manager->max_fd; fd++) {
if (manager->sockets[fd]) {
close_socket(manager->sockets[fd]);
}
}

free(manager);
}

2.2 Epoll模型

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
#ifdef __linux__
#include <sys/epoll.h>

// Epoll事件类型
typedef enum {
EPOLL_EVENT_READ = EPOLLIN,
EPOLL_EVENT_WRITE = EPOLLOUT,
EPOLL_EVENT_ERROR = EPOLLERR | EPOLLHUP,
EPOLL_EVENT_EDGE_TRIGGERED = EPOLLET
} epoll_event_t;

// Epoll管理器
typedef struct {
int epoll_fd;
struct epoll_event* events;
int max_events;
socket_info_t** sockets;
int socket_count;
int capacity;
} epoll_manager_t;

// 初始化Epoll管理器
epoll_manager_t* epoll_manager_init(int max_events) {
epoll_manager_t* manager = (epoll_manager_t*)malloc(sizeof(epoll_manager_t));
if (!manager) {
return NULL;
}

manager->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (manager->epoll_fd < 0) {
printf("错误: 创建epoll失败: %s\n", strerror(errno));
free(manager);
return NULL;
}

manager->events = (struct epoll_event*)malloc(max_events * sizeof(struct epoll_event));
if (!manager->events) {
close(manager->epoll_fd);
free(manager);
return NULL;
}

manager->max_events = max_events;
manager->socket_count = 0;
manager->capacity = 1024;

manager->sockets = (socket_info_t**)calloc(manager->capacity, sizeof(socket_info_t*));
if (!manager->sockets) {
free(manager->events);
close(manager->epoll_fd);
free(manager);
return NULL;
}

printf("初始化Epoll管理器: fd=%d, 最大事件=%d\n",
manager->epoll_fd, max_events);

return manager;
}

// 添加Socket到Epoll
int epoll_add_socket(epoll_manager_t* manager, socket_info_t* sock_info,
uint32_t events) {
if (!manager || !sock_info || sock_info->fd < 0) {
return -1;
}

struct epoll_event ev;
ev.events = events;
ev.data.fd = sock_info->fd;

if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, sock_info->fd, &ev) < 0) {
printf("错误: 添加Socket到epoll失败: %s\n", strerror(errno));
return -1;
}

// 扩展Socket数组
if (sock_info->fd >= manager->capacity) {
int new_capacity = sock_info->fd + 1024;
socket_info_t** new_sockets = (socket_info_t**)realloc(
manager->sockets, new_capacity * sizeof(socket_info_t*));
if (!new_sockets) {
return -1;
}

// 初始化新分配的内存
for (int i = manager->capacity; i < new_capacity; i++) {
new_sockets[i] = NULL;
}

manager->sockets = new_sockets;
manager->capacity = new_capacity;
}

manager->sockets[sock_info->fd] = sock_info;
manager->socket_count++;

printf("添加Socket到Epoll: fd=%d, 事件=0x%x\n", sock_info->fd, events);

return 0;
}

// 修改Epoll中的Socket事件
int epoll_modify_socket(epoll_manager_t* manager, socket_info_t* sock_info,
uint32_t events) {
if (!manager || !sock_info || sock_info->fd < 0) {
return -1;
}

struct epoll_event ev;
ev.events = events;
ev.data.fd = sock_info->fd;

if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_MOD, sock_info->fd, &ev) < 0) {
printf("错误: 修改epoll事件失败: %s\n", strerror(errno));
return -1;
}

printf("修改Epoll事件: fd=%d, 事件=0x%x\n", sock_info->fd, events);

return 0;
}

// 从Epoll移除Socket
int epoll_remove_socket(epoll_manager_t* manager, socket_info_t* sock_info) {
if (!manager || !sock_info || sock_info->fd < 0) {
return -1;
}

if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_DEL, sock_info->fd, NULL) < 0) {
printf("错误: 从epoll移除Socket失败: %s\n", strerror(errno));
return -1;
}

if (sock_info->fd < manager->capacity) {
manager->sockets[sock_info->fd] = NULL;
}
manager->socket_count--;

printf("从Epoll移除Socket: fd=%d\n", sock_info->fd);

return 0;
}

// Epoll等待事件
int epoll_wait_events(epoll_manager_t* manager, int timeout_ms) {
if (!manager) {
return -1;
}

int ready = epoll_wait(manager->epoll_fd, manager->events,
manager->max_events, timeout_ms);

if (ready < 0) {
printf("错误: epoll_wait失败: %s\n", strerror(errno));
} else if (ready == 0) {
printf("Epoll超时\n");
} else {
printf("Epoll就绪: %d个事件\n", ready);
}

return ready;
}

// 获取就绪的Socket
socket_info_t* epoll_get_ready_socket(epoll_manager_t* manager, int index) {
if (!manager || index < 0 || index >= manager->max_events) {
return NULL;
}

int fd = manager->events[index].data.fd;
if (fd < 0 || fd >= manager->capacity) {
return NULL;
}

return manager->sockets[fd];
}

// 获取Socket事件
uint32_t epoll_get_socket_events(epoll_manager_t* manager, int index) {
if (!manager || index < 0 || index >= manager->max_events) {
return 0;
}

return manager->events[index].events;
}

// Epoll服务器示例
void epoll_server_example(void) {
printf("=== Epoll服务器示例 ===\n");

// 创建Epoll管理器
epoll_manager_t* manager = epoll_manager_init(1024);
if (!manager) {
return;
}

// 创建监听Socket
socket_info_t* listen_sock = create_socket(SOCKET_TYPE_TCP, "0.0.0.0", 8080);
if (!listen_sock) {
close(manager->epoll_fd);
free(manager->events);
free(manager->sockets);
free(manager);
return;
}

set_socket_option(listen_sock, SO_REUSEADDR, 1);
set_non_blocking(listen_sock, 1);

if (bind_socket(listen_sock) < 0 || listen_socket(listen_sock, 1024) < 0) {
close_socket(listen_sock);
close(manager->epoll_fd);
free(manager->events);
free(manager->sockets);
free(manager);
return;
}

// 添加监听Socket到Epoll
epoll_add_socket(manager, listen_sock, EPOLL_EVENT_READ | EPOLL_EVENT_EDGE_TRIGGERED);

printf("Epoll服务器启动,等待连接...\n");

// 主循环
for (int loop = 0; loop < 20; loop++) { // 限制循环次数用于演示
int ready = epoll_wait_events(manager, 5000); // 5秒超时

if (ready <= 0) {
continue;
}

for (int i = 0; i < ready; i++) {
socket_info_t* sock = epoll_get_ready_socket(manager, i);
uint32_t events = epoll_get_socket_events(manager, i);

if (!sock) {
continue;
}

if (sock == listen_sock) {
// 处理新连接
if (events & EPOLL_EVENT_READ) {
while (1) {
socket_info_t* client = accept_socket(listen_sock);
if (!client) {
break; // 没有更多连接
}

set_non_blocking(client, 1);
epoll_add_socket(manager, client,
EPOLL_EVENT_READ | EPOLL_EVENT_EDGE_TRIGGERED);
}
}
} else {
// 处理客户端数据
if (events & EPOLL_EVENT_READ) {
char buffer[4096];

while (1) {
ssize_t received = recv_data(sock, buffer, sizeof(buffer) - 1, 0);

if (received > 0) {
buffer[received] = '\0';
printf("客户端消息: %s\n", buffer);

// 回显消息
send_data(sock, buffer, received, 0);
} else if (received == 0) {
// 连接关闭
printf("客户端断开连接: fd=%d\n", sock->fd);
epoll_remove_socket(manager, sock);
close_socket(sock);
break;
} else {
// EAGAIN或EWOULDBLOCK,没有更多数据
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break;
} else {
// 其他错误
printf("接收错误: %s\n", strerror(errno));
epoll_remove_socket(manager, sock);
close_socket(sock);
break;
}
}
}
}

if (events & EPOLL_EVENT_ERROR) {
printf("Socket错误: fd=%d\n", sock->fd);
epoll_remove_socket(manager, sock);
close_socket(sock);
}
}
}
}

// 清理资源
for (int i = 0; i < manager->capacity; i++) {
if (manager->sockets[i]) {
close_socket(manager->sockets[i]);
}
}

close(manager->epoll_fd);
free(manager->events);
free(manager->sockets);
free(manager);
}

// 销毁Epoll管理器
void epoll_manager_destroy(epoll_manager_t* manager) {
if (!manager) {
return;
}

// 关闭所有Socket
for (int i = 0; i < manager->capacity; i++) {
if (manager->sockets[i]) {
close_socket(manager->sockets[i]);
}
}

close(manager->epoll_fd);
free(manager->events);
free(manager->sockets);
free(manager);

printf("销毁Epoll管理器\n");
}

#endif // __linux__

3. HTTP服务器实现

3.1 HTTP协议解析

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
#include <ctype.h>

// HTTP方法
typedef enum {
HTTP_METHOD_GET = 1,
HTTP_METHOD_POST,
HTTP_METHOD_PUT,
HTTP_METHOD_DELETE,
HTTP_METHOD_HEAD,
HTTP_METHOD_OPTIONS,
HTTP_METHOD_UNKNOWN
} http_method_t;

// HTTP状态码
typedef enum {
HTTP_STATUS_OK = 200,
HTTP_STATUS_CREATED = 201,
HTTP_STATUS_NO_CONTENT = 204,
HTTP_STATUS_BAD_REQUEST = 400,
HTTP_STATUS_UNAUTHORIZED = 401,
HTTP_STATUS_FORBIDDEN = 403,
HTTP_STATUS_NOT_FOUND = 404,
HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
HTTP_STATUS_INTERNAL_ERROR = 500,
HTTP_STATUS_NOT_IMPLEMENTED = 501,
HTTP_STATUS_SERVICE_UNAVAILABLE = 503
} http_status_t;

// HTTP头部
typedef struct http_header {
char* name;
char* value;
struct http_header* next;
} http_header_t;

// HTTP请求
typedef struct {
http_method_t method;
char* uri;
char* version;
http_header_t* headers;
char* body;
size_t body_length;
size_t content_length;
} http_request_t;

// HTTP响应
typedef struct {
http_status_t status;
char* version;
char* reason_phrase;
http_header_t* headers;
char* body;
size_t body_length;
} http_response_t;

// 解析HTTP方法
http_method_t parse_http_method(const char* method_str) {
if (!method_str) {
return HTTP_METHOD_UNKNOWN;
}

if (strcmp(method_str, "GET") == 0) {
return HTTP_METHOD_GET;
} else if (strcmp(method_str, "POST") == 0) {
return HTTP_METHOD_POST;
} else if (strcmp(method_str, "PUT") == 0) {
return HTTP_METHOD_PUT;
} else if (strcmp(method_str, "DELETE") == 0) {
return HTTP_METHOD_DELETE;
} else if (strcmp(method_str, "HEAD") == 0) {
return HTTP_METHOD_HEAD;
} else if (strcmp(method_str, "OPTIONS") == 0) {
return HTTP_METHOD_OPTIONS;
}

return HTTP_METHOD_UNKNOWN;
}

// HTTP方法转字符串
const char* http_method_to_string(http_method_t method) {
switch (method) {
case HTTP_METHOD_GET: return "GET";
case HTTP_METHOD_POST: return "POST";
case HTTP_METHOD_PUT: return "PUT";
case HTTP_METHOD_DELETE: return "DELETE";
case HTTP_METHOD_HEAD: return "HEAD";
case HTTP_METHOD_OPTIONS: return "OPTIONS";
default: return "UNKNOWN";
}
}

// HTTP状态码转字符串
const char* http_status_to_string(http_status_t status) {
switch (status) {
case HTTP_STATUS_OK: return "OK";
case HTTP_STATUS_CREATED: return "Created";
case HTTP_STATUS_NO_CONTENT: return "No Content";
case HTTP_STATUS_BAD_REQUEST: return "Bad Request";
case HTTP_STATUS_UNAUTHORIZED: return "Unauthorized";
case HTTP_STATUS_FORBIDDEN: return "Forbidden";
case HTTP_STATUS_NOT_FOUND: return "Not Found";
case HTTP_STATUS_METHOD_NOT_ALLOWED: return "Method Not Allowed";
case HTTP_STATUS_INTERNAL_ERROR: return "Internal Server Error";
case HTTP_STATUS_NOT_IMPLEMENTED: return "Not Implemented";
case HTTP_STATUS_SERVICE_UNAVAILABLE: return "Service Unavailable";
default: return "Unknown";
}
}

// 添加HTTP头部
int add_http_header(http_header_t** headers, const char* name, const char* value) {
if (!headers || !name || !value) {
return -1;
}

http_header_t* header = (http_header_t*)malloc(sizeof(http_header_t));
if (!header) {
return -1;
}

header->name = strdup(name);
header->value = strdup(value);
header->next = *headers;

if (!header->name || !header->value) {
free(header->name);
free(header->value);
free(header);
return -1;
}

*headers = header;

return 0;
}

// 查找HTTP头部
const char* find_http_header(const http_header_t* headers, const char* name) {
if (!headers || !name) {
return NULL;
}

const http_header_t* current = headers;
while (current) {
if (strcasecmp(current->name, name) == 0) {
return current->value;
}
current = current->next;
}

return NULL;
}

// 释放HTTP头部
void free_http_headers(http_header_t* headers) {
while (headers) {
http_header_t* next = headers->next;
free(headers->name);
free(headers->value);
free(headers);
headers = next;
}
}

// 解析HTTP请求行
int parse_request_line(const char* line, http_request_t* request) {
if (!line || !request) {
return -1;
}

char method_str[16];
char uri[2048];
char version[16];

int parsed = sscanf(line, "%15s %2047s %15s", method_str, uri, version);
if (parsed != 3) {
printf("错误: 无效的请求行: %s\n", line);
return -1;
}

request->method = parse_http_method(method_str);
request->uri = strdup(uri);
request->version = strdup(version);

if (!request->uri || !request->version) {
free(request->uri);
free(request->version);
return -1;
}

printf("解析请求行: %s %s %s\n", method_str, uri, version);

return 0;
}

// 解析HTTP头部行
int parse_header_line(const char* line, http_request_t* request) {
if (!line || !request) {
return -1;
}

char* colon = strchr(line, ':');
if (!colon) {
return -1;
}

// 提取头部名称
size_t name_len = colon - line;
char* name = (char*)malloc(name_len + 1);
if (!name) {
return -1;
}

strncpy(name, line, name_len);
name[name_len] = '\0';

// 去除名称末尾空格
while (name_len > 0 && isspace(name[name_len - 1])) {
name[--name_len] = '\0';
}

// 提取头部值
char* value = colon + 1;
while (*value && isspace(*value)) {
value++;
}

// 去除值末尾空格
char* value_end = value + strlen(value) - 1;
while (value_end > value && isspace(*value_end)) {
*value_end-- = '\0';
}

int result = add_http_header(&request->headers, name, value);

// 特殊处理Content-Length
if (strcasecmp(name, "Content-Length") == 0) {
request->content_length = atoi(value);
}

printf("解析头部: %s: %s\n", name, value);

free(name);

return result;
}

// 解析HTTP请求
http_request_t* parse_http_request(const char* data, size_t data_len) {
if (!data || data_len == 0) {
return NULL;
}

http_request_t* request = (http_request_t*)malloc(sizeof(http_request_t));
if (!request) {
return NULL;
}

memset(request, 0, sizeof(http_request_t));

// 查找请求头和请求体的分界线
const char* header_end = strstr(data, "\r\n\r\n");
if (!header_end) {
free(request);
return NULL;
}

size_t header_len = header_end - data;

// 复制头部数据
char* header_data = (char*)malloc(header_len + 1);
if (!header_data) {
free(request);
return NULL;
}

strncpy(header_data, data, header_len);
header_data[header_len] = '\0';

// 按行分割头部
char* line = strtok(header_data, "\r\n");
int is_first_line = 1;

while (line) {
if (is_first_line) {
if (parse_request_line(line, request) < 0) {
free(header_data);
free(request->uri);
free(request->version);
free(request);
return NULL;
}
is_first_line = 0;
} else {
parse_header_line(line, request);
}

line = strtok(NULL, "\r\n");
}

free(header_data);

// 处理请求体
if (request->content_length > 0) {
const char* body_start = header_end + 4; // 跳过\r\n\r\n
size_t remaining = data_len - (body_start - data);

if (remaining >= request->content_length) {
request->body = (char*)malloc(request->content_length + 1);
if (request->body) {
memcpy(request->body, body_start, request->content_length);
request->body[request->content_length] = '\0';
request->body_length = request->content_length;
}
}
}

printf("解析HTTP请求完成: %s %s\n",
http_method_to_string(request->method), request->uri);

return request;
}

// 创建HTTP响应
http_response_t* create_http_response(http_status_t status) {
http_response_t* response = (http_response_t*)malloc(sizeof(http_response_t));
if (!response) {
return NULL;
}

memset(response, 0, sizeof(http_response_t));

response->status = status;
response->version = strdup("HTTP/1.1");
response->reason_phrase = strdup(http_status_to_string(status));

if (!response->version || !response->reason_phrase) {
free(response->version);
free(response->reason_phrase);
free(response);
return NULL;
}

// 添加默认头部
add_http_header(&response->headers, "Server", "C-HTTP-Server/1.0");
add_http_header(&response->headers, "Connection", "close");

return response;
}

// 设置HTTP响应体
int set_response_body(http_response_t* response, const char* body,
const char* content_type) {
if (!response || !body) {
return -1;
}

free(response->body);

response->body_length = strlen(body);
response->body = (char*)malloc(response->body_length + 1);
if (!response->body) {
response->body_length = 0;
return -1;
}

strcpy(response->body, body);

// 设置Content-Length
char content_length_str[32];
snprintf(content_length_str, sizeof(content_length_str), "%zu", response->body_length);
add_http_header(&response->headers, "Content-Length", content_length_str);

// 设置Content-Type
if (content_type) {
add_http_header(&response->headers, "Content-Type", content_type);
}

return 0;
}

// 序列化HTTP响应
char* serialize_http_response(const http_response_t* response, size_t* output_len) {
if (!response || !output_len) {
return NULL;
}

// 计算响应大小
size_t total_size = 0;

// 状态行
total_size += strlen(response->version) + 1 + 3 + 1 +
strlen(response->reason_phrase) + 2; // HTTP/1.1 200 OK\r\n

// 头部
const http_header_t* header = response->headers;
while (header) {
total_size += strlen(header->name) + 2 + strlen(header->value) + 2; // Name: Value\r\n
header = header->next;
}

total_size += 2; // \r\n

// 响应体
if (response->body) {
total_size += response->body_length;
}

// 分配内存
char* output = (char*)malloc(total_size + 1);
if (!output) {
return NULL;
}

char* ptr = output;

// 写入状态行
ptr += sprintf(ptr, "%s %d %s\r\n",
response->version, response->status, response->reason_phrase);

// 写入头部
header = response->headers;
while (header) {
ptr += sprintf(ptr, "%s: %s\r\n", header->name, header->value);
header = header->next;
}

// 写入空行
ptr += sprintf(ptr, "\r\n");

// 写入响应体
if (response->body && response->body_length > 0) {
memcpy(ptr, response->body, response->body_length);
ptr += response->body_length;
}

*output_len = ptr - output;
output[*output_len] = '\0';

return output;
}

// 释放HTTP请求
void free_http_request(http_request_t* request) {
if (!request) {
return;
}

free(request->uri);
free(request->version);
free(request->body);
free_http_headers(request->headers);
free(request);
}

// 释放HTTP响应
void free_http_response(http_response_t* response) {
if (!response) {
return;
}

free(response->version);
free(response->reason_phrase);
free(response->body);
free_http_headers(response->headers);
free(response);
}

3.2 简单HTTP服务器

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
// HTTP路由处理函数类型
typedef http_response_t* (*http_handler_t)(const http_request_t* request);

// HTTP路由
typedef struct http_route {
http_method_t method;
char* path;
http_handler_t handler;
struct http_route* next;
} http_route_t;

// HTTP服务器
typedef struct {
socket_info_t* listen_sock;
http_route_t* routes;
char* document_root;
int max_connections;
int current_connections;
} http_server_t;

// 创建HTTP服务器
http_server_t* create_http_server(const char* ip, int port, const char* document_root) {
http_server_t* server = (http_server_t*)malloc(sizeof(http_server_t));
if (!server) {
return NULL;
}

memset(server, 0, sizeof(http_server_t));

// 创建监听Socket
server->listen_sock = create_socket(SOCKET_TYPE_TCP, ip, port);
if (!server->listen_sock) {
free(server);
return NULL;
}

// 设置Socket选项
set_socket_option(server->listen_sock, SO_REUSEADDR, 1);

// 设置文档根目录
if (document_root) {
server->document_root = strdup(document_root);
} else {
server->document_root = strdup(".");
}

server->max_connections = 100;

printf("创建HTTP服务器: %s:%d, 文档根目录: %s\n",
ip ? ip : "0.0.0.0", port, server->document_root);

return server;
}

// 添加路由
int add_http_route(http_server_t* server, http_method_t method,
const char* path, http_handler_t handler) {
if (!server || !path || !handler) {
return -1;
}

http_route_t* route = (http_route_t*)malloc(sizeof(http_route_t));
if (!route) {
return -1;
}

route->method = method;
route->path = strdup(path);
route->handler = handler;
route->next = server->routes;

if (!route->path) {
free(route);
return -1;
}

server->routes = route;

printf("添加路由: %s %s\n", http_method_to_string(method), path);

return 0;
}

// 查找路由
http_handler_t find_http_route(const http_server_t* server,
http_method_t method, const char* path) {
if (!server || !path) {
return NULL;
}

const http_route_t* route = server->routes;
while (route) {
if (route->method == method && strcmp(route->path, path) == 0) {
return route->handler;
}
route = route->next;
}

return NULL;
}

// 默认处理函数
http_response_t* default_handler(const http_request_t* request) {
http_response_t* response = create_http_response(HTTP_STATUS_NOT_FOUND);
if (response) {
set_response_body(response, "<h1>404 Not Found</h1>", "text/html");
}
return response;
}

// Hello World处理函数
http_response_t* hello_handler(const http_request_t* request) {
http_response_t* response = create_http_response(HTTP_STATUS_OK);
if (response) {
const char* html = "<html><body><h1>Hello, World!</h1><p>C HTTP Server</p></body></html>";
set_response_body(response, html, "text/html");
}
return response;
}

// API处理函数
http_response_t* api_handler(const http_request_t* request) {
http_response_t* response = create_http_response(HTTP_STATUS_OK);
if (response) {
const char* json = "{\"message\": \"Hello from API\", \"status\": \"success\"}";
set_response_body(response, json, "application/json");
}
return response;
}

// 处理HTTP请求
void handle_http_request(http_server_t* server, socket_info_t* client_sock) {
if (!server || !client_sock) {
return;
}

char buffer[8192];
ssize_t received = recv_data(client_sock, buffer, sizeof(buffer) - 1, 0);

if (received <= 0) {
return;
}

buffer[received] = '\0';

// 解析HTTP请求
http_request_t* request = parse_http_request(buffer, received);
if (!request) {
// 发送400错误
http_response_t* error_response = create_http_response(HTTP_STATUS_BAD_REQUEST);
if (error_response) {
set_response_body(error_response, "<h1>400 Bad Request</h1>", "text/html");

size_t response_len;
char* response_data = serialize_http_response(error_response, &response_len);
if (response_data) {
send_data(client_sock, response_data, response_len, 0);
free(response_data);
}

free_http_response(error_response);
}
return;
}

// 查找路由处理函数
http_handler_t handler = find_http_route(server, request->method, request->uri);
if (!handler) {
handler = default_handler;
}

// 调用处理函数
http_response_t* response = handler(request);
if (response) {
size_t response_len;
char* response_data = serialize_http_response(response, &response_len);
if (response_data) {
send_data(client_sock, response_data, response_len, 0);
free(response_data);
}

free_http_response(response);
}

free_http_request(request);
}

// 启动HTTP服务器
int start_http_server(http_server_t* server) {
if (!server) {
return -1;
}

// 绑定和监听
if (bind_socket(server->listen_sock) < 0 ||
listen_socket(server->listen_sock, 128) < 0) {
return -1;
}

printf("HTTP服务器启动成功,等待连接...\n");

// 主循环
while (1) {
socket_info_t* client = accept_socket(server->listen_sock);
if (client) {
server->current_connections++;

printf("接受HTTP连接: fd=%d, 当前连接数: %d\n",
client->fd, server->current_connections);

// 处理请求
handle_http_request(server, client);

// 关闭连接
close_socket(client);
server->current_connections--;

// 限制演示循环次数
static int request_count = 0;
if (++request_count >= 5) {
printf("演示完成,停止服务器\n");
break;
}
}
}

return 0;
}

// HTTP服务器示例
void http_server_example(void) {
printf("=== HTTP服务器示例 ===\n");

// 创建HTTP服务器
http_server_t* server = create_http_server("0.0.0.0", 8080, "./www");
if (!server) {
return;
}

// 添加路由
add_http_route(server, HTTP_METHOD_GET, "/", hello_handler);
add_http_route(server, HTTP_METHOD_GET, "/hello", hello_handler);
add_http_route(server, HTTP_METHOD_GET, "/api", api_handler);
add_http_route(server, HTTP_METHOD_POST, "/api", api_handler);

// 启动服务器
start_http_server(server);

// 清理资源
http_route_t* route = server->routes;
while (route) {
http_route_t* next = route->next;
free(route->path);
free(route);
route = next;
}

close_socket(server->listen_sock);
free(server->document_root);
free(server);
}

4. 网络编程示例

4.1 综合示例

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
// 网络编程演示主函数
int main(void) {
printf("C语言网络编程演示\n");
printf("===================\n\n");

// 基本Socket示例
printf("1. 基本Socket示例\n");
tcp_client_example();
printf("\n");

tcp_server_example();
printf("\n");

udp_example();
printf("\n");

// I/O多路复用示例
printf("2. I/O多路复用示例\n");
select_server_example();
printf("\n");

#ifdef __linux__
epoll_server_example();
printf("\n");
#endif

// HTTP服务器示例
printf("3. HTTP服务器示例\n");
http_server_example();
printf("\n");

printf("网络编程演示完成\n");

return 0;
}

总结

C语言在网络编程领域具有以下优势:

核心技术

  1. Socket编程 - 提供底层网络通信接口
  2. I/O多路复用 - 支持高并发连接处理
  3. 协议实现 - 可以实现各种网络协议
  4. 性能优化 - 精确控制内存和系统资源

实际应用

  1. Web服务器 - Apache、Nginx等高性能服务器
  2. 数据库系统 - MySQL、PostgreSQL等数据库服务器
  3. 网络设备 - 路由器、交换机固件开发
  4. 游戏服务器 - 实时多人在线游戏后端
  5. 物联网 - 嵌入式设备网络通信

关键要点

  1. 内存管理 - 正确分配和释放网络缓冲区
  2. 错误处理 - 完善的网络异常处理机制
  3. 并发控制 - 合理使用多路复用技术
  4. 协议遵循 - 严格按照网络协议标准实现
  5. 安全考虑 - 防范网络攻击和数据泄露

C语言的网络编程能力使其成为构建高性能、可靠网络应用的理想选择,在服务器开发、网络设备和系统级网络编程中发挥着重要作用。

版权所有,如有侵权请联系我