You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言gets/scanf读取含换行HTTP请求字符串提前终止问题求解

问题原因说明

原有读取方式的固有逻辑直接导致读取不符合预期:

  • gets() 是逐行读取函数,碰到第一个换行符就会终止读取,还会自动丢弃读到的换行符,因此最多只能读到第一行的请求行内容,无法获取后续空行和请求体。另外该函数因为存在无法限制读取长度的缓冲区溢出漏洞,早已被C标准废弃,生产环境禁止使用。
  • 无格式参数的scanf("%s") 读取规则是碰到任意空白字符(空格、换行、制表符)就终止,因此碰到GET后面的空格就会停止,只能读到第一个单词。
实现方案

按照需求分两步实现读取逻辑,全程用安全的fgets()做逐段读取,手动控制读取终止条件和校验逻辑:

  1. 先读取第一行请求行,解析路径字段做校验:如果路径不是/api,直接终止读取流程;如果校验通过,把第一行内容写入目标缓冲区。
  2. 校验通过后继续读取后续内容,累计统计读到的换行符数量,当换行符总数达到3个时立即停止读取,保证刚好读完三行(请求行、空行、请求体行),全程控制写入长度不超过缓冲区大小,避免溢出。

参考实现代码:

#include <stdio.h>
#include <string.h>

int main() {
    char msg_send[1000] = {0};
    // 记录缓冲区当前写入位置偏移
    size_t offset = 0;
    char line_buf[256] = {0};
    int newline_cnt = 0;

    // 读取第一行做路径校验
    if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
        return -1;
    }
    // 统计第一行内的换行符
    char* p = line_buf;
    while (*p) {
        if (*p == '\n') newline_cnt++;
        p++;
    }
    // 拆分第一行的方法、路径、版本字段
    char method[16] = {0}, path[256] = {0}, version[16] = {0};
    sscanf(line_buf, "%15s %255s %15s", method, path, version);
    // 路径不符合要求直接终止流程
    if (strcmp(path, "/api") != 0) {
        return 0;
    }
    // 校验通过将第一行写入目标缓冲区
    size_t line_len = strlen(line_buf);
    if (offset + line_len < sizeof(msg_send) - 1) {
        memcpy(msg_send + offset, line_buf, line_len);
        offset += line_len;
    } else {
        return -1;
    }

    // 继续读取后续内容,直到累计读到3个换行符
    while (newline_cnt < 3 && fgets(line_buf, sizeof(line_buf), stdin) != NULL) {
        p = line_buf;
        while (*p && newline_cnt < 3) {
            if (*p == '\n') {
                newline_cnt++;
            }
            p++;
        }
        line_len = strlen(line_buf);
        if (offset + line_len < sizeof(msg_send) - 1) {
            memcpy(msg_send + offset, line_buf, line_len);
            offset += line_len;
        } else {
            return -1;
        }
        if (newline_cnt >= 3) break;
    }
    // 手动补字符串结束符
    msg_send[offset] = '\0';

    // 后续可直接操作msg_send处理完整内容
    printf("读取到的完整内容:\n%s", msg_send);
    return 0;
}
逻辑说明
  • 读取第一行时用带长度限制的sscanf做格式拆分,直接拿到path字段做比对,满足路径错误即终止的需求,同时避免字段读取溢出。
  • 全程维护写入偏移量offset,每次写入前判断剩余缓冲区空间,不会出现越界写入问题。
  • 逐字符统计换行符数量,累计到3个就停止,刚好匹配“读到第三个换行符终止”的规则,不会多读也不会少读。
  • 所有读取操作都用fgets指定最大读取长度,不存在缓冲区溢出风险。

内容的提问来源于stack exchange,提问作者User 1999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 02:57:18