c - 即使以二进制模式写入文件也会损坏
问题描述
我正在尝试以二进制模式将文件(任何类型)从一台 PC(客户端)发送到另一台 PC(服务器),但是如果我在两个终端之间的本地主机上运行程序,程序运行正常(视频、音乐一切正常)
但是,当我在虚拟机(ubuntu 20.04 上的两台机器)中运行客户端时,传输的文件会损坏(例如,传输后在主机中接收到扭曲的图像)。损坏的图像
我该怎么办,如果有人可以帮助我,我将不胜感激。 完整代码
这里附上TCP模式下建立连接后的代码 Client.c *
write(sockfd, file_name, sizeof(file_name)); // send the file name to server
struct stat obj;
stat(file_name, &obj);
int file_size = obj.st_size;
write(sockfd, &file_size, sizeof(file_size)); // send the file size to server
system("clear");
printf("Sending %s .....\n\nFile size = %.3fkB\n",file_name,(1.0*file_size)/1024);
unsigned char buf[512]; // to store chunks of data from the target file
int count = file_size/512;
int remain = file_size % 512;
struct timeval start,end;
gettimeofday(&start,NULL); //Starting time
while(count--){ // stores the data in buf array
bzero(buf,512);
fread(buf,1,sizeof(buf),f);
// if(n == 512)
write(sockfd,buf,sizeof(buf)); // send the data stored in buf to Server
}
// the last remaining chunk which is less than 512 Byte
if(remain){
bzero(buf,512);
fread(buf,1,remain,f);
write(sockfd,buf,remain); // send the data stored in buf to Server
}
gettimeofday(&end,NULL); //Ending time
double t1 =(end.tv_usec-start.tv_usec); //microseconds count
double time_taken= (end.tv_sec-start.tv_sec)+(t1/MILLION); // total time taken
printf("\n%s sent successfully\n",file_name);
printf("\n\n%lfsec taken.........\n",time_taken);
fclose(f); // close the file
close(sockfd); //close the socket
return 0;
服务器.c *
// reading filename from the client side
bzero(file_name,512);
read(newsockfd,file_name,sizeof(file_name));
int file_size;
read(newsockfd,&file_size,sizeof(file_size));
FILE *fp;
fp = fopen(file_name,"wb"); // open corresponding file in write-binary mode
int count = file_size/512;
int remain = file_size%512;
unsigned char buf[512]; // to store a chunk of data coming from client file
system("clear");
printf("Recieving \"%s\" .....\n",file_name);
while(count--){
bzero(buf,512); // clears the buf array
read(newsockfd,buf,sizeof(buf)); // read the corresponding data coming from client to buf array
fwrite(buf,1,sizeof(buf),fp); // write the corresponding data from buf array to file
}
// the last remaining chunk which is less than 512 Byte
if(remain){
bzero(buf,512); // clears the buf array
read(newsockfd,buf,remain); // read the corresponding data coming from client to buf array
fwrite(buf,1,remain,fp); // write the corresponding data from buf array to file
}
// fseek(fp, 0, SEEK_SET);
printf("\n%s received successfully\n",file_name);
fclose(fp); // close the file
close(newsockfd); //close interconnected socket
close(sockfd); // close server socket
return 0;
}
解决方案
很难说,但看起来很像一些额外的数据被插入到图像文件的中间。由于它以方块形式发生,我猜您的图像文件是 JPEG。
这可能是为什么:
read(newsockfd,buf,sizeof(buf)); // read UP TO 512 bytes
fwrite(buf,1,sizeof(buf),fp); // write EXACTLY 512 bytes
read
要求 512 字节(buf 的大小)。但它可能无法准确读取 512 个字节。如果您调用read
并且还没有收到字节,它会等待一些。但是如果有一些接收到的字节,但小于 512,它将返回它到目前为止收到的那些,返回值告诉你它返回了多少字节。
您的程序会忽略这一点并写入 512 个字节,无论读取了多少字节。
你应该只写read
它读取的字节数。而且您应该继续循环,直到总字节数与您期望的数字相匹配。不要计算read
调用次数,计算字节数。
推荐阅读
- puppeteer - Puppeteer:在页面请求中获取正确的框架元素
- svg - Flutter SVG 仅在热重启后渲染
- python - 当你有很多变量时如何进行智能数据分析
- python - Python - 找不到时更改寻求的字典键
- docker - 用于 docker 图像的 Skopeo 工具 - 重新标记
- typescript - Typescript - 键入一个函数,该函数接受一个字符串数组并以字符串作为键创建输出
- c# - 如何使用c#中的程序检查堆栈内存的大小
- c# - 没有文件夹命名空间时在 MailKit 中打开邮件文件夹
- ruby-on-rails - 使用 RSPEC 测试环境相关路由
- android - Gradle 多模块依赖 - 一起使用 api 和 testImplementation