2016-05-02 13 views
0

Ich versuche, einfachen HTTP-Client mit c, zu schreiben, wenn ich mein Programm einige Zeit ausführe, bekomme ich Daten von der Website irgendwann nicht. zu spezifischen recv() blockiert werden, und die Verbindung heruntergefahren. Was ist der beste Weg, um mit diesem Problem umzugehen? Ich möchte immer noch die Daten der Website erhalten.einfacher HTTP-Client c recv() blockiert

ZeroMemory(&hints, sizeof(hints)); 
hints.ai_family = AF_UNSPEC; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_protocol = IPPROTO_TCP; 
// Resolve the server address and port 
if (iResult = getaddrinfo(s1, "http", &hints, &result)) { 
    printf("getaddrinfo failed with error: %d\n", iResult); 
    WSACleanup(); 
    return 1; 
} 
// Attempt to connect to an address until one succeeds 

for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { 

    // Create a SOCKET for connecting to server 
    ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
     ptr->ai_protocol); 
    if (ConnectSocket == INVALID_SOCKET) { 
     printf("socket failed with error: %ld\n", WSAGetLastError()); 
     WSACleanup(); 
     return 1; 
    } 


    iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); 
    if (iResult == SOCKET_ERROR) { 
     closesocket(ConnectSocket); 
     ConnectSocket = INVALID_SOCKET; 
     continue; 
    } 
    break; 
} 

freeaddrinfo(result); 

if (ConnectSocket == INVALID_SOCKET) { 
    printf("Unable to connect to server!\n"); 
    WSACleanup(); 
    return 1; 
} 


// Send an initial buffer 
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0); 
if (iResult == SOCKET_ERROR) { 
    printf("send failed with error: %d\n", WSAGetLastError()); 
    closesocket(ConnectSocket); 
    WSACleanup(); 
    return 1; 
} 

// shutdown the connection since no more data will be sent 
iResult = shutdown(ConnectSocket, SD_SEND); 
if (iResult == SOCKET_ERROR) { 
    printf("shutdown failed with error: %d\n", WSAGetLastError()); 
    closesocket(ConnectSocket); 
    WSACleanup(); 
    return 1; 
} 

// Receive until the peer closes the connection 

do {   
    iResult = recv(ConnectSocket, recvbuf, recvbuflen-1, 0); 
    if (iResult > 0) { 
     flag = 1; 
     recvbuf[iResult] = '\0'; 
     printf("%s\n",recvbuf); 
    } 
    else if (iResult == 0) { 
      if(!flag) { 
       printf("conection close before recv data\n"); 
      } else { 
       printf("conection close\n"); 
       break; 
      } 
    } 
    else { 
     printf("recv failed with error: %d\n", WSAGetLastError()); 
    } 
} while(iResult>1); 


// cleanup 
closesocket(ConnectSocket); 
WSACleanup(); 

return 0; 

}

i HTTP-Protokoll-Konzept verwendet haben und zu jeder URL Ich habe in diesem templet versucht gesendet: sendbuf = "GET/[url path] HTTP 1.0/r/nHost: [www .pure_url.com]/r/n/r/n "

bearbeiten: Ich habe [DaSourcerer beraten] versucht, zu HTTP/1.1 geändert und Verbindung hinzugefügt: Schließen, noch einige Zeit bekomme ich die Daten nicht mal .

auch hinzugefügt I:

int tcp_timeout=10000; 
unsigned int sz = sizeof(tcp_timeout); 
setsockopt(ConnectSocket, SOL_SOCKET, SO_RCVTIMEO, 
(char*)&tcp_timeout, sz); 

diese Idee nicht helfen.

+0

Post-Stück Code, anstatt einige Links zu geben. Das würde helfen, schnell zu reagieren –

Antwort

0

Ich denke, Ihre Timeouts sind zu streng. Ihre gesendeten Header werden außerdem Server dazu veranlassen, auf weitere Eingaben zu warten. Versuchen Sie folgendes:

GET /path HTTP/1.1 
Host: example.com 
Connection: close 

Es trägt auch zu erwähnen, dass Host ein Header in HTTP/1.1 eingeführt ist. Es hat keine Bedeutung in HTTP/1.0. Sie könnten auch an RFC 7230, section 3.3.3 interessiert sein, da Sie mit großer Wahrscheinlichkeit auf chunk-codierte Nachrichten in HTTP/1.1 stoßen werden. Aber keine Sorge: Es kann mit einer einfachen Zustandsmaschine geparst werden.