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

C语言实现HTTP服务器处理视频POST请求:无法检测末尾boundary

问题分析与解决方法

核心问题

  • strstr()不支持二进制数据:strstr()是字符串查找函数,会把遇到的第一个'\0'当作字符串结束符停止搜索。但视频是二进制文件,内容中大概率包含'\0',直接用它搜索会提前终止,找不到后续的boundary。
  • Boundary可能跨缓冲区:你每次固定读取BUFFERSIZE字节,但boundary可能刚好被拆分在两个连续的缓冲区中,单次搜索单个缓冲区自然找不到完整的boundary。
  • 写入逻辑冗余:当read()返回的实际字节数re小于BUFFERSIZE时,你依然写入BUFFERSIZE字节,会把缓冲区中未被覆盖的0写入文件,虽然不影响boundary存在,但属于无效写入。

修复步骤

1. 替换strstr()为二进制安全的查找函数

自己实现一个基于内存块的查找函数,不依赖'\0'作为结束标志,根据实际读取的字节长度搜索:

// 二进制安全的内存查找,返回首次匹配的指针,未找到返回NULL
void* mem_find(const void* haystack, size_t haystack_len, const void* needle, size_t needle_len) {
    if (needle_len == 0 || haystack_len < needle_len) {
        return NULL;
    }

    const unsigned char* h = (const unsigned char*)haystack;
    const unsigned char* n = (const unsigned char*)needle;

    for (size_t i = 0; i <= haystack_len - needle_len; ++i) {
        size_t j;
        for (j = 0; j < needle_len; ++j) {
            if (h[i + j] != n[j]) {
                break;
            }
        }
        if (j == needle_len) {
            return (void*)(h + i);
        }
    }
    return NULL;
}

2. 处理跨缓冲区的Boundary

保留上一次缓冲区中未搜索完的尾部数据(长度为boundary长度-1),避免跨缓冲区的boundary被拆分后无法匹配:

#define BOUNDARY_LEN (strlen(boundaryarr))
unsigned char buf[BUFFERSIZE + BOUNDARY_LEN - 1]; // 预留空间存上一次的尾部
size_t leftover = 0; // 上一次未处理的尾部字节数
int fla = 0;
void* endoffile = NULL;

while (!endoffile) {
    memset(buf + leftover, 0, BUFFERSIZE);
    int re = read(i, buf + leftover, BUFFERSIZE);
    if (re <= 0) {
        if (fla == 0) {
            fla = 1;
            continue;
        } else {
            break;
        }
    }
    if (fla == 1) {
        fla = 0;
    }

    size_t total_len = leftover + re;
    num_read += re;

    // 用自定义函数查找boundary
    endoffile = mem_find(buf, total_len, boundaryarr, BOUNDARY_LEN);
    if (endoffile) {
        // 计算写入长度:从buf开头到boundary前的位置
        size_t write_len = (unsigned char*)endoffile - buf - 3; // 对应原逻辑的-3
        if (write_len > 0) {
            write(newfd, buf, write_len);
        }
        close(newfd);
    } else {
        // 保留最后BOUNDARY_LEN-1字节,用于下一次搜索跨缓冲区的boundary
        if (total_len >= BOUNDARY_LEN - 1) {
            memcpy(buf, buf + total_len - (BOUNDARY_LEN - 1), BOUNDARY_LEN - 1);
            leftover = BOUNDARY_LEN - 1;
            // 写入除保留部分外的有效数据
            write(newfd, buf, total_len - leftover);
        } else {
            // 当前总长度不足boundary长度,全部保留
            leftover = total_len;
        }
    }
}

3. 修正写入长度问题

修复后的代码只写入实际读取到的有效数据,避免了原逻辑中写入多余0的问题。

额外说明

  • 打印缓冲区看不到boundary是因为视频二进制数据中的不可打印字符干扰了终端输出,实际数据是存在的,所以写入文件后能正常显示。
  • 确认boundaryarr格式正确:HTTP multipart的boundary在内容中是以--{boundary}开头的,如果你提取的boundary没有包含前面的--,需要补上,否则会匹配失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 05:42:37