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封装函数。