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

C语言Web服务器调用read()接收POST请求内容被截断问题求助

问题根因

你的代码存在多个逻辑错误是POST数据丢失的核心原因:

  • 未拼接跨缓冲区的HTTP内容:每次read的数据直接覆盖recvLine,没有和之前读取的内容拼接。如果请求头和请求体的分隔符\r\n\r\n被拆分到两次read的返回结果中,你根本无法匹配到分隔符,或者只能匹配到截断的内容。
  • 未以字符串规则处理缓冲区内容:read系统调用只会返回读到的字节数,不会主动在缓冲区末尾加\0结束符,你直接用fprintf(stdout, "%s", recvLine)和strstr操作,会导致内存越界,读到不属于请求的垃圾内容,也可能截断合法请求。
  • 找到分隔符后直接终止读取:\r\n\r\n只是请求头和请求体的分隔符,你匹配到分隔符后仅处理了当前缓冲区中分隔符后的部分数据就break结束读取,剩下还没到达内核缓冲区、或者还没被read读上来的请求体内容全部被丢弃。
  • 未按Content-Length读取请求体:HTTP POST请求的请求体长度由请求头中的Content-Length字段指定,你完全没有解析这个字段,根本不知道应该读多少字节的请求体,不可能完整接收数据。
  • 无效的错误判断分支:你的while循环入口条件是readSock > 0,循环内部的else if (readSock <= 0 && endOfPost == NULL)分支永远不可能被触发,异常退出逻辑完全失效。
  • 缓冲区清空逻辑错误:每次循环结束你只memset前10字节的recvLine,如果你的recvLine实际长度大于10,剩下的残留内容会干扰下一次读取的内容解析。

修复方案

你需要按照HTTP协议的标准接收逻辑调整代码:

  1. 定义一个足够大的全局接收缓冲区,每次read后把新读到的内容追加到缓冲区末尾,同时记录已经读到的总字节数,每次追加后手动在缓冲区末尾加\0保证字符串操作安全。
  2. 先读取完整的请求头:在整个接收缓冲区中匹配\r\n\r\n,匹配到之后先从请求头中解析出Content-Length字段的值,得到请求体的总长度。
  3. 计算已经读到的请求体长度 = 总已读字节数 - (分隔符位置 + 4),如果已经读到的请求体长度小于Content-Length指定的长度,继续read直到读满指定长度的请求体再停止。
  4. 再对完整的请求体做strtok拆分处理。

核心代码修复示例

// 示例:定义接收缓冲区,总大小可根据需求调整
#define RECV_BUF_SIZE 4096
char recvBuf[RECV_BUF_SIZE];
int totalRead = 0;
int readSock;
// 先读满请求头,同时防止缓冲区溢出
while ((readSock = read(acceptSock, recvBuf + totalRead, RECV_BUF_SIZE - totalRead - 1)) > 0) {
    totalRead += readSock;
    // 手动加结束符保证字符串操作安全
    recvBuf[totalRead] = '\0';
    // 整个缓冲区查找分隔符
    char* endOfHeader = strstr(recvBuf, "\r\n\r\n");
    if (endOfHeader != NULL) {
        // 先解析Content-Length
        char* contentLenStr = strstr(recvBuf, "Content-Length: ");
        if (contentLenStr == NULL) {
            // 没有请求体直接处理
            break;
        }
        int contentLen = atoi(contentLenStr + strlen("Content-Length: "));
        // 计算已经收到的请求体长度
        int receivedBodyLen = totalRead - (endOfHeader - recvBuf + 4);
        // 没读满就继续读
        while (receivedBodyLen < contentLen && totalRead < RECV_BUF_SIZE - 1) {
            readSock = read(acceptSock, recvBuf + totalRead, RECV_BUF_SIZE - totalRead - 1);
            if (readSock <= 0) break;
            totalRead += readSock;
            receivedBodyLen += readSock;
            recvBuf[totalRead] = '\0';
        }
        break;
    }
}
// 后续处理完整的recvBuf内容即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:36:05