2017-06-02 281 views
0

我想實現一個程序,將任何文件從服務器傳輸到客戶端。我必須使用讀/寫功能讀取和寫入數據(用於學校作業)。這裏是服務器和客戶端的代碼。通過套接字傳輸文件c

server.c

char buffer[512];   

    if((file = open(strTable[1], O_RDONLY)) == -1) { perror("Open"); } 

    while(read(file, buffer, sizeof(buffer)) != 0) 
    { 
     size = strlen(buffer)+1; 
     if(write(newsock, &size, sizeof(size)) < 0) { perror("Write"); exit(1); } 

     write_all(newsock, buffer, strlen(buffer)+1); 
    } 

    size = 4; 
    if(write(newsock, &size, sizeof(size)) < 0) { perror("Write"); exit(1); } 
    write_all(newsock, "end", 4); 

它打開strTable [1](其中包含我想讀取文件),它讀取的sizeof(緩衝區)字節,然後我發送給客戶多少字節我將寫入套接字,然後我發送字節。這裏是write_all函數。

int write_all(int sock, char* buffer, int size) 
{ 
    int nwrite, sent = 0; 

    while(sent < size) 
    { 
     if((nwrite = write(sock, buffer + sent, size - sent)) < 0) 
     { perror("Write"); exit(1); } 

     sent += nwrite; 
    } 

    return sent; 
} 

client.c

if((file = open(absolute, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) 
       { perror("Open"); }  

while(true) 
     { 
      received = 0; 

      /* Read the desired readable size */ 
      if(read(sock, &size, sizeof(size)) < 0) 
      { perror("Read"); pthread_exit(NULL); } 

      /* Read all data */ 
      while(received < size) 
      { 
       if((nread = read(sock, buffer + received, size - received)) < 0) 
       { perror("Read"); pthread_exit(NULL); } 

       received += nread; 
      } 

      if(strncmp(buffer, "end", 4) == 0) { break; } 

      write_all(file, buffer, strlen(buffer)+1); 
     } 

客戶端打開一個文件(絕對),並在其所寫的東西它讀取。它首先讀取它需要讀取的尺寸,然後它不會停下來讀取,直到達到該尺寸。如果客戶端讀取「結束」,則服務器已停止寫入套接字,以便客戶端停止讀取。

問題是我無法打開轉移後的文件。我讀了一些我無法打開的圖像。我還讀了一個file.txt,我寫了一些隨機單詞,這似乎被複制了,但它也有一些垃圾(其照片編號爲2)。爲什麼我得到這個以及如何正確地從套接字傳輸文件?

enter image description here

enter image description here

+0

[tag:encoding]的相關性使我不知所措。 – EJP

+0

'read'和'write'都返回讀取或寫入的字節數,這可能比請求的少。 –

回答

1

常見的問題。 read()不終止緩衝區,因此使用strlen()作爲計數無效。讀/寫循環應該是這樣的:

int count; 
while ((count = read(inFD, buffer, sizeof buffer)) > 0) 
{ 
    if (write(outFD, buffer, count) < 0) 
    { 
     perrror("write"); // at least 
     break; 
    } 
} 

其次是錯誤處理如下:

if (count < 0) 
{ 
    perror("read"); // at least 
} 

你的第二個問題帶有假設"end"將自身作爲一個獨立的消息被接收。這不能保證。您必須通過在每個文件之後關閉套接字來使用流結束,或者在每個文件之前發送長度,並且只從每個文件的流中讀取許多字節。但是,由於您已經發送了長度,發送"end"無論如何都毫無意義。

+0

您還需要檢查來自'write'的返回值,因爲它可能寫入少於count個字節,在這種情況下,您需要再次寫入調用才能寫入更多。 –

+0

特別是在非阻塞模式下。某些特定的底層對象(如管道和文件)可能會保證小於某個限制的寫入不會返回短值,但是您需要檢查計數實際上是否小於該限制,並且outFD是限制適用的某些內容... –

+0

@ChrisDodd對不起,我誤解了。根據Posix規範,不在*阻止*模式,但我應該檢查錯誤。 – EJP