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

fopen()返回NULL但文件存在的TCP服务器技术问题

问题排查与修复

主要问题点

1. 文件名缓冲区未每次重置

filename在主循环外仅执行了一次bzero清空操作,每次处理新客户端连接时,上一次请求的文件名会残留在缓冲区中,新读取的字符会直接拼接在旧内容后面,导致最终的文件名是两次请求的字符串混合体,自然无法找到对应文件。

2. 文件名读取循环逻辑存在缺陷

初始状态下c数组未初始化,第一次进入while (c[0] != '\0')循环时,c[0]是随机值,可能直接跳过循环或错误执行;同时循环的判断-读取顺序容易导致字符处理不完整。

修复方案

1. 将文件名缓冲区清空移至主循环内

每次接受新连接后立即重置缓冲区,避免旧数据残留:

while (1) {
    int newSock;
    bzero(filename, MAX_FILENAME); // 移到此处,每次处理新连接都重置缓冲区

    if ((newSock = accept(sock, res->ai_addr, &res->ai_addrlen)) == -1) {
        errx(2, "Error while accepting.");
    }
    // 后续代码...
}

2. 修正文件名读取循环逻辑

先读取第一个字符再进入循环判断,消除初始值不确定的问题:

char c[1];
// 先读取第一个字符,确保循环初始状态可控
if (readn(newSock, c, 1) == -1) {
    errx(2, "%s", strerror(errno));
}
while (c[0] != '\0') {
    strncat(filename, c, 1);
    if (readn(newSock, c, 1) == -1) {
        errx(2, "%s", strerror(errno));
    }
}

3. 额外验证步骤

可以在fopen前打印文件名的详细信息,排查是否存在不可见字符(如换行符、空格):

printf("待打开文件名: '%s'\n", filename);
// 打印十六进制格式,检查异常字符
for (size_t j=0; j<strlen(filename); j++) {
    printf("%02x ", (unsigned char)filename[j]);
}
printf("\n");

如果输出包含非预期字符,说明客户端发送的文件名存在问题,需要同步排查客户端代码。

(可选)处理未使用的offset变量

代码中读取了4字节的offset但未做任何处理,如果这是客户端协议的一部分,需补充对应的逻辑;如果是冗余代码,可直接删除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 20:45:05