2011-11-30 60 views
1

我正在下載200個字符塊中的在線.dat文件,並且一些數據丟失。大多數,但不是所有的塊完全下載,但有些只是部分下載,當我將接收到的數據直接打印到本地文本文件時,缺少字符。使用C中的套接字在TCP傳輸中丟失數據

謝謝。

我正在使用的程序如下。

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/stat.h> 
#include <netdb.h> 
#include <string.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <malloc.h> 

#define NOT_EOF 1 
#define REACHED_EOF 0 
#define BUFFER_SIZE 200 

struct sockaddr_storage their_addr; 
socklen_t addr_size; 
char inputData[200]; 
int newsocket; 
struct timeval timeout; 
char sendStr[100]; 
char method[] = "GET"; 

char *buffer= (char *)malloc(2*BUFFER_SIZE*sizeof(char)); 

FILE *testdata=fopen("testRecv.txt","w"); 

struct addrinfo hints, *result; 
memset (&hints, 0, sizeof hints); 
hints.ai_family = AF_INET; 
hints.ai_socktype = SOCK_STREAM; 

if(getaddrinfo("www.blahblah.com","80" 
        , &hints, &result)!=0) 
{ 
    freeaddrinfo(result); 
    puts("Unable to resolve hostname."); 
    exit(1); 
} 

newsocket = socket(result->ai_family, result->ai_socktype, 0); 
if(newsocket == FAILURE) 
{ 
    puts("Unable to create socket."); 
    freeaddrinfo(result); 
    close(newsocket); 
    exit(1); 
    } 

memset(&timeout, 0, sizeof(timeout)); 
timeout.tv_sec= 10; 
timeout.tv_usec= 0; 
setsockopt(newsocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); 
setsockopt(newsocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); 

if(connect(newsocket, result->ai_addr, result->ai_addrlen) == -1) 
    { 
    puts("Could not connect."); 
    freeaddrinfo(result); 
    close(newsocket); 
    exit(1); 
    } 

strcpy(sendStr,method); 
strcat(sendStr," /"); 
strcat(sendStr,subdomain); 
strcat(sendStr," HTTP/1.0\r\nHost: "); 
strcat(sendStr,hostname); 
strcat(sendStr,"\r\n\r\n"); 

if(send(newsocket,sendStr,strlen(sendStr),0) == FAILURE) 
printf("Unable to send message\n"); 

while(not_eof=NOT_EOF) 
    { 
     bytes_recieved=recv(newsocket,buffer,BUFFER_SIZE,0); 

     fprintf(testdata,"%s",buffer); 

     if(bytes_recieved == 0 || *(buffer+bytes_recieved) == EOF) 
     not_eof=REACHED_EOF; 
    } 
+0

向我們展示'recv()'的實際代碼。當然,你不是隻調用一次? – NPE

+2

這是所有的代碼?我看不到文件寫入。 – hmjd

+0

'while(not_eof = NOT_EOF)'這是不對的。在C中,'='是賦值操作符。 –

回答

2

您不能只打一次電話recv。由於您處於阻止模式,因此您必須在循環中調用它並檢查其返回值是否爲正值。如果是負數,則會出現錯誤,如果爲零,則套接字已按順序關閉。

+0

對不起,我在程序中的其他地方收到了一個循環,所有的值都是正值,但數據丟失了。我會更新上述程序。 –

+0

@Julia你的更新沒有意義。 'not_eof'在哪裏改變?你如何彙總每個'recv'調用的輸出結果? – Artefacto

+0

我已更新我的問題以在代碼中顯示請求的信息。 –

2

recv調用不保證在一次調用中接收所有數據。對於200字節的數據大小,人們可以期待整個數據在一次調用中,但並非總是如此。如果它不是全部在一次通話中收到,則需要再次調用recv。

編輯所示的變化(如果它是真實的代碼)似乎仍然需要工作。無論返回值如何,都會進行fprintf調用。因此,循環執行兩次,第二次recv調用失敗,緩衝區將被寫入兩次。此外,我不認爲buffer保證爲空終止,因此fprintf(...%s...)調用可能會有不可預知的結果。但似乎主要的問題是不能處理返回-1(錯誤情況)的可能性。從理論上講,這會導致它無限循環。實際上,它會像目前所示無限循環,無論因爲while循環有一個等號,並且每次迭代都會爲該標誌指定1(但我認爲這是編輯中的拼寫錯誤)。

+1

recv直到它到達文件的結尾,所以理論上如果我只收到每個recv數據的一半,最終我應該收到它的全部,但是有兩倍的調用次數。但是,我收到的數據中的幾個地方缺少實際字符。這會導致我另一個問題。是否有可能在接收數據方面不成功,並且數量有限,導致一些丟失的數據?我對這個主題了解不多,而且我可以在互聯網上找到的信息頁面都說TCP是可靠的。 –

+0

幾乎100%保證了你的代碼在某處的錯誤。 TCP是可靠的,並且大多數Web服務器也是如此。例如您需要仔細考慮recv的返回值。您應該向我們展示接收數據並將其寫入文件的實際完整代碼。 – nos

+0

我已更新我的問題以顯示您在代碼中請求的所有信息。 –