c - 即使以二进制模式写入后,文件也被损坏

标签 c sockets client-server binaryfiles file-transfer

我正在尝试以二进制模式将文件(任何类型)从一台PC(客户端)发送到另一台PC(服务器)
但是如果我在两个终端之间的本地主机上运行该程序,它就可以正常工作(视频,音乐一切正常)
但是,当我在虚拟机(两台机器都在ubuntu 20.04上)上运行客户端时,传输的文件已损坏(例如,传输后在主机中接收到失真的镜像)。 corrupted image
我该怎么办,如果有人可以帮助我,我将不胜感激。
Full code
我在这里以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;
Server.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调用的数量,请计算字节数。

关于c - 即使以二进制模式写入后,文件也被损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65229643/

相关文章:

C 动态字符串数组

sql-server - 限制服务器端返回的行数(强制限制)

php - 如何使用php从服务器在客户端打印机上打印

使用 TextMate 编译 C 代码

php - 从 php 加载 c 库

c - 是否(不)可以在 C 源代码中使用特殊字符?

c - Socket : Connect will spend 2 minutes looking for IP before it timesOut. 如何减少该时间?

c - 基于 epoll 的非阻塞 ssl_read() 陷入循环

php - 保持每个客户端在php中的连接处于打开状态

linux - 如何从客户端在服务器上执行脚本?