2012-10-01 51 views
1

当我尝试在我编写的简单服务器和客户端应用程序之间传输文件时,我遇到了问题。文件传输成功,但接收端(服务器端)的文件大小不同。 我在客户端打开文件,使用fseek()来查找文件的大小。然后我使用fread()将其读入char类型的缓冲区。我使用sendto()发送这个缓冲区,因为我必须使用UDP套接字。 在服务器端,我使用recvfrom()来存储它,并使用fwrite()将它写入另一个文件。但是当我检查文件的大小时,它更大。即使它应该是一个文本文件,我也无法打开它。 你能给我一些关于我可能会出错的指示吗?这是通过套接字发送文件的最佳方式吗?有更好的方法发送文件吗?通过UDP发送时文件大小不同

感谢

代码客户端服务器端

//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); 
     } 
+1

使用'diff'工具查看*文件的不同*。然后用这些知识找出可能引入错误的地方:例如在某个地方是否有整个数据包大小的部分被跳过?请记住:** UDP不保证数据包传输**,因此如果切换到TCP“解决”(或更改)观察到的问题。 – 2012-10-01 00:34:53

+0

您使用的是什么代码?另外,它们不会将UDP调用为“不可靠数据报协议”。如果可能的话,最好只使用TCP连接。 – marinus

+0

@pst我相信这个问题不是由使用UDP引起的。我感觉错误在于我的实现打开,复制和传输文件。我只发送小文件来检查我的程序。问题是即使我发送1 3 Kb文件,它显示为30KB或40KB。 – FieryDragon87

回答

1

有几个问题与您的代码。

发信人:

  • 你如何分配file_buffer?如果文件大于缓冲区,该怎么办? (可能这不会导致手头上的问题。)

  • 您只检查fread的返回值是否为<= 0。事实上,如果发生错误或EOF,则返回值可以是小于文件完整大小的任何值。 (可能这不会导致手头上的问题。)

  • 您将strlen(file_buffer)而不是file_size传递给sendto系统调用。 strlen查找文件可能包含或不包含的NUL个字节。它可能不包含任何内容,因为你说它是一个文本文件。

    • 如果文件包含至少一个NUL字节,数据包将在第一个NUL字节之前被截断,并且您不会传输文件的全部内容。
    • 如果文件不包含NUL字节,strlen将在读入缓冲区之后扫描超出文件末尾。您的程序将因为strlen扫描到未分配的内存地址而崩溃,否则您将在文件末尾发送额外的垃圾。

在接收机中:

  • 您忽略从recvfrom返回值其是已接收的分组的有效载荷的长度。之后,你无法知道你收到了多少数据。

  • 当你fwrite的结果,你通过作为大小,而不是实际收到的数据量。这是一个固定值(BUFSIZE),它可能比您的文件大。写在磁盘上的文件将包含超出文件末尾的垃圾。

+0

非常好,但'返回值可以是小于文件全部大小的任何值'只有在发生* EOF *时才为真。如果发生错误,返回值将为-1,并且会有一个伴随的'errno'。 – EJP

+0

@Celada非常感谢。这样愚蠢的错误:(我传递客户端的'file_size'值,然后使用'recvfrom'调用返回的值作为我的'fwrite'。现在一切正常。 现在我使用固定大小我的'file_buffer',但是就像你说过的,如果文件比这个更大,我可能会遇到问题,现在我只是从基础知识开始学习,让程序更加复杂,所以我的下一步就是打破任何文件,然后发送它。非常感谢! – FieryDragon87

+0

@Celada我也记下你说的关于检查fread的返回值的内容。 – FieryDragon87