首页 > 解决方案 > 即使以二进制模式写入文件也会损坏

问题描述

我正在尝试以二进制模式将文件(任何类型)从一台 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;

}

标签: csocketsclient-serverbinaryfilesfile-transfer

解决方案


很难说,但看起来很像一些额外的数据被插入到图像文件的中间。由于它以方块形式发生,我猜您的图像文件是 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调用次数,计算字节数。


推荐阅读