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
相关产品推荐
相关产品推荐

