1. 应用层数据生成与缓冲区管理
任务目标
编写一个C语言程序,模拟应用层生成HTTP GET请求数据,并将其写入一个可管理的发送缓冲区。该缓冲区将作为后续TCP/IP协议栈封装(传输层、网络层、链路层)的输入数据源。
核心实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF_SIZE 2048
typedef struct {
unsigned char data[BUF_SIZE];
int len;
} SendBuffer;
/* 生成HTTP GET请求,返回写入缓冲区的字节数 */
int http_get_request(const char *host, const char *path, SendBuffer *buf) {
if (!host || !path || !buf) return -1;
int n = snprintf((char *)buf->data, BUF_SIZE,
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: MiniTCP/1.0\r\n"
"Accept: */*\r\n"
"Connection: close\r\n"
"\r\n",
path, host);
if (n < 0 || n >= BUF_SIZE) return -1; /* 缓冲区不足 */
buf->len = n;
return n;
}
/* 将缓冲区内容按十六进制+ASCII格式打印,便于验证 */
void dump_buffer(const SendBuffer *buf) {
for (int i = 0; i < buf->len; i++) {
if (i % 16 == 0) printf("\n%04X ", i);
printf("%02X ", buf->data[i]);
if (i % 16 == 15 || i == buf->len - 1) {
printf(" ");
for (int j = (i / 16) * 16; j <= i; j++) {
unsigned char c = buf->data[j];
printf("%c", (c >= 32 && c <= 126) ? c : '.');
}
}
}
printf("\n总长度: %d 字节\n", buf->len);
}
int main(void) {
SendBuffer tx = {0};
int len = http_get_request("www.example.com", "/index.html", &tx);
if (len < 0) {
fprintf(stderr, "请求生成失败\n");
return 1;
}
printf("=== 应用层发送缓冲区内容 ===");
dump_buffer(&tx);
return 0;
}
编译与运行
gcc -o http_gen http_gen.c
./http_gen
验证方法
- 编译通过:gcc无报错、无警告(建议加 -Wall 编译)。
- 输出检查:程序打印的缓冲区内容应以
GET /index.html HTTP/1.1开头,包含Host: www.example.com头字段,并以空行(\r\n\r\n)结束。 - 长度验证:末尾打印的总长度应与实际请求字符串字节数一致(可手工用
printf的返回值核对)。 - 缓冲区边界:将
BUF_SIZE临时改为较小值(如64)重新编译,程序应返回错误而非越界写入。
关键说明
SendBuffer结构体中的data字段即应用层交付给下层协议的完整数据单元;len记录有效字节数,避免下层协议扫描整个数组。- HTTP请求以
\r\n作为行结束符,报文头与报文体之间必须有空行,代码中已正确包含。 - 本程序只负责应用层数据生成与缓冲区管理,不涉及socket发送;后续案例将把
tx.data和tx.len作为输入传递给TCP封装函数。