当我尝试在我编写的简单服务器和客户端应用程序之间传输文件时,我遇到了问题。文件成功传输,但接收端(服务器端)的文件大小不同。 我在客户端打开文件,使用fseek()查找文件的大小。然后我使用fread()将它读入char类型的缓冲区。我使用sendto()发送此缓冲区,因为我必须使用UDP套接字。 在服务器端,我使用recvfrom()来存储它,并使用fwrite()将其写入另一个文件。但是当我检查文件的大小时,它要大得多。即使它应该是一个文本文件,我也无法打开它。 你能给我一些关于我可能出错的地方吗?这也是通过套接字发送文件的最佳方式吗?是否有更好的方法来发送文件?
谢谢
客户端代码
//Writing code to open file and copy it into buffer
fseek(fp, 0, SEEK_END);
size_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
if(fread(file_buffer, file_size, 1, fp)<=0)
{
printf("Unable to copy file into buffer! \n");
exit(1);
}
//Sending file buffer
if(sendto(sock, file_buffer, strlen(file_buffer), 0, (struct sockaddr *) &serv_addr, serv_len)<0)
{
printf("Error sending the file! \n");
exit(1);
}
bzero(file_buffer, sizeof(file_buffer));
服务器端的代码以接收文件
//Receiving file from client
char file_buffer[BUFSIZE];
if(recvfrom(sock, file_buffer, BUFSIZE, 0, (struct sockaddr *) &client_addr, &client_addr_size)<0)
{
printf("Error receiving file.");
exit(1);
}
char new_file_name[] = "copied_";
strcat(new_file_name,file_name);
FILE *fp;
fp = fopen(new_file_name,"w+");
if(fwrite(file_buffer, 1, sizeof(file_buffer), fp)<0)
{
printf("Error writing file! \n");
exit(1);
}
答案 0 :(得分:1)
您的代码存在一些问题。
发件人:
您如何分配file_buffer
?如果文件大于缓冲区怎么办? (可能这不会导致手头的问题。)
您只需检查fread
的返回值是否为<= 0
。实际上,如果发生错误或EOF,则返回值可以是小于文件完整大小的任何值。 (可能这不会导致手头的问题。)
您将strlen(file_buffer)
而不是file_size
传递给sendto
系统调用。 strlen
查找文件可能包含或不包含的NUL字节。它可能不包含任何内容,因为你说它是一个文本文件。
strlen
将扫描超出文件末尾的读取缓冲区。您的程序将崩溃,因为strlen
扫描到未分配的内存地址,或者您将在文件末尾发送额外的垃圾。在收件人中:
您忽略recvfrom
的返回值,该值是收到的数据包的有效负载长度。之后,您无法知道收到的数据量。
当您fwrite
结果时,您会将sizeof(file_buffer)
作为大小而不是实际接收的数据量。这是一个固定值(BUFSIZE
),可能比您的文件大。写在磁盘上的文件将包含超出文件末尾的垃圾。