2012-10-01 50 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