2016-01-17 62 views
1

我正在編寫一個簡單的客戶端/服務器應用程序,並遇到了一個非常奇怪的問題。客戶端讀取其他文件後不讀取任何數據

我想發送一個.zip文件到客戶端,然後再發送一些數據。 發送.zip工作正常,服務器寫入套接字,客戶端從套接字讀取,正如預期的那樣。

之後的問題是 服務器運行正常,並一直寫入套接字,但客戶端不會讀取任何內容。無論我嘗試發送什麼,它都會停留在接下來的read()調用中。

我檢查過套接字描述符是否正常,它們是。我也認爲,可能沒有足夠的數據在客戶端讀取套接字,但肯定是。

我也試圖做同樣的讀/寫之前和發送該.zip文件後:它工作正常之前,但客戶沒有看到它後發送該.zip文件。 我沒有想法。

這是我用來發送的.zip功能:

typedef struct thData{ 
int idThread; //thread ID 
int cl; //client descriptor 
}thData; 

void send_info(struct thData tdL) 
{ 
    char file_path[256]="v1.zip"; 
    char sd_buffer[256]; 
    bzero(sd_buffer, 256); 

    FILE *fd = fopen(file_path, "rb"); 
    if(fd == NULL) 
    { 
     printf("ERROR: %s not found.\n", file_path); 
     exit(1); 
    } 


    int read_size; 
    int write_size; 
    while((read_size = fread(sd_buffer, sizeof(char), 256, fd)) > 0) 
    { 
     if((write_size=write(tdL.cl, sd_buffer, read_size)) < 0) 
     { 
      perror("ERROR: writing to client: \n"); 
      break; 
     } 
     bzero(sd_buffer, 256); 
    } 
} 

我使用接收的.zip什麼:

void receive_info(int sd) //sd being the socket descriptor 
{ 
    char* file_path = "subject.zip"; 
    char received_buffer[256]; 

    int total_received=0; 
    int total_wrote=0; 

    FILE *fd = fopen(file_path, "wb"); 
    if(fd == NULL) 
     printf("Cannot open %s\n", file_path); 
    else 
    { 
     bzero(received_buffer, 256); 
     int read_size = 0; 
     while((read_size = read(sd, received_buffer, 256)) > 0) 
     { 
      total_received=total_received+read_size; 

      int write_size = fwrite(received_buffer, sizeof(char), read_size, fd); 
      total_wrote=total_wrote+read_size; 

      if(write_size < read_size) 
      { 
       perror("ERROR: \n"); 
      } 
      bzero(received_buffer, 256); 
      if (read_size == 0 || read_size != 256) 
      { 
       break; 
      } 
     } 
     if(read_size < 0) 
     { 

      perror("ERROR: reading: "); 
      exit(1); 

     } 
     fclose(fd); 
    } 
} 

任何幫助將不勝感激。

回答

1

我認爲問題在於你讀得太多。

在TCP中,從一個對端發送到另一個對端的報文中沒有邊界。它只是一個字節流,從recv/read()收到的作品與send/write()發送的作品沒有任何關係(原則上)。

現在,假設您的ZIP文件長度爲300個字節,並且您的額外數據長度爲10個字節。您的發件人代碼將執行:

  • 寫入256個字節(ZIP的第一部分)。
  • 寫入44個字節(ZIP的最後一部分)。
  • 寫入10個字節(額外的數據)。

和接收器的代碼就可以了:

  • 閱讀256,得到256個字節(從ZIP第一塊)。
  • 讀取256,獲取54個字節(ZIP中的最後一部分加上額外的數據)。
  • 讀取XXX個字節,永遠等待!

如果你仔細看的ZIP文件,你可能會看到這些額外的字節在subject.zip結束。

解決方案如果您不想關閉並打開另一個套接字,則會使協議更復雜一些。例如,您可以在包含文件大小的文件(標題)之前發送結構。這樣接收機就會知道什麼時候停止閱讀。

PS:請注意,您的代碼有一些有風險的邊緣。例如,write()可能不會寫入所有給定的字節,但您沒有檢查該字節;你是不是關閉文件...

PS2:我覺得奇怪的是,你覺得有必要寫sizeof(char),而不是僅僅1但你寫256,而不是sizeof(sd_buffer)

+0

謝謝!你對額外的字節是正確的! – user3211838

相關問題