netcopy网络拷贝程序接收端生成out.bin大小为0问题排查
错误排查与修复方案
直接原因(导致out.bin为0的核心问题)
- 客户端打开待发送文件的模式错误:你调用
fopen(argv[2], "w+"),w+模式会先清空源文件内容,待发送的文件直接被截断为0长度,后续read读取不到任何数据,没有任何内容发送到服务端,自然生成的out.bin长度为0。 - while循环条件运算符优先级错误:C语言中
>运算符优先级高于=,你的原代码count = read(...) > 0实际执行逻辑是先判断read返回值是否大于0,将得到的布尔值(1或0)赋值给count,就算文件读取正常,每次也只会向socket写入1字节,最终文件内容也会出错。
其他需要修复的隐患
- 混用C库文件接口与系统调用:你用
fopen打开文件,又用read/write系统调用操作文件描述符,C库的缓冲机制和系统调用直接操作的逻辑不互通,容易出现数据不一致的问题,建议要么全用open/read/write/close系统调用,要么全用fread/fwrite等C库标准IO接口。 - 未处理短读/短写场景:网络socket的
read、write调用不保证每次都能处理你指定的长度,需要循环执行确保所有数据完成读写。 - 未使用二进制模式打开文件:如果传输二进制文件,非二进制模式下会自动转换换行符,导致文件损坏,建议打开文件时用
rb(只读二进制)、wb(写入二进制)模式。 - 服务端退出码错误:程序正常执行完成却调用
exit(1)(代表异常退出),应该改为exit(0)。
修复后的核心代码片段
客户端(copy.c)
// 改为只读二进制模式打开待发送文件 f = fopen(argv[2], "rb"); if (f == NULL) { perror("打开待发送文件失败"); exit(1); } int file_no = fileno(f); printf("sizeof buffer = %d\n", sizeof(buffer)); ssize_t count; // 加括号修正优先级,先赋值再判断 while( (count = read(file_no, buffer, sizeof(buffer))) > 0 ) { ssize_t written = 0; // 循环处理短写,保证全部数据写入socket while (written < count) { ssize_t res = write(sockfd, buffer + written, count - written); if (res < 0) { perror("socket写入失败"); exit(1); } written += res; } bzero(buffer, sizeof(buffer)); } fclose(f);
服务端(netcopy.c)
// 改为二进制写入模式创建输出文件 f = fopen("out.bin", "wb"); if (f == NULL) { perror("创建输出文件失败"); exit(1); } int file_no = fileno(f); ssize_t n; // 加括号修正优先级 while( (n = read(connfd, binbuff, sizeof(binbuff))) > 0) { ssize_t written = 0; // 循环处理短写,保证全部数据写入文件 while (written < n) { ssize_t res = write(file_no, binbuff + written, n - written); if (res < 0) { perror("文件写入失败"); exit(1); } written += res; } bzero(binbuff, sizeof(binbuff)); } fclose(f); // 正常退出返回0 exit(0);
内容的提问来源于stack exchange,提问作者Alexandru Goia
相关产品推荐
相关产品推荐

