2016-04-02 4 views
0

Ich führe ein Linux-Programm in C geschrieben, die in regelmäßigen Abständen Daten durch Parsen einer HTTP-Antwort empfangen würde, einige Zahlen knacken und dann das Ergebnis per HTTP GET einer anderen Webseite melden.Den Grund für recv Blockierung für immer verstehen

Mein Problem ist, dass manchmal eine der Instanzen "einfrieren" würde.

Mit Blick auf top kann ich sehen, dass es in sk_wait_data Zustand ist und das Anhängen eines Debuggers zeigt, dass es von einem recv Aufruf blockiert wird.

Hier ist eine Minimalversion des Codes, der die TCP-Verbindung funktioniert (es von http://www.linuxhowtos.org/C_C++/socket.htm angepasst wurde):

int connectTCP(const char* host, const char* page, int portno) { 
    int sockfd; 

    struct sockaddr_in serv_addr; 
    struct hostent *server; 

    // Create socket // 
    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 


    // Get ip from hostname // 
    server = gethostbyname(host); 
    if (server == NULL) 
     error("ERROR, can not find host\n"); 

    memset((char *) &serv_addr, 0, sizeof(serv_addr)); 


    serv_addr.sin_family = AF_INET; 
    memcpy((char *)&serv_addr.sin_addr.s_addr, // Destination 
      (char *)server->h_addr, // Source 
      server->h_length);  // Size 
    serv_addr.sin_port = htons(portno); 

    // Conect to socket // 
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
     error("ERROR connecting"); 

    return sockfd; 

} 

char* httpGet(const char* host, const char* page, int portno) { 
    int sockfd, n; 

    sockfd = connectTCP(host, page, portno); 
    memset(buffer, 0, sizeof(buffer)); 

    sprintf(buffer, "GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", page, host); 

    n = send(sockfd,buffer,strlen(buffer), 0); 

    if (n < 0) 
    error("ERROR writing to socket"); 

    int count = 0; 
    do { 
    n = recv(sockfd, buffer + count, BUFFER_MAX_SIZE - count, 0); 
    if (n < 0) { 
     error("ERROR reading from socket"); 

    } 

    count += n; 
    } while(n != 0); 

    close(sockfd); 

    return buffer; 
} 
+0

Was passiert, wenn die Seite größer als der Puffer ist? –

+0

Was passiert, wenn das erste recv() weniger Bytes zurückgibt als der GET-Sende-String, der noch im Puffer liegt? –

+0

Sie müssen mehr debuggen, oder zeigen Sie, wie Ihre HTML-Analyse und Pufferverwaltung oder beides funktioniert. –

Antwort

0

Bugs im Code:

  1. Wenn recv() Null zurückgibt Sie whould schließe den Sockel und höre auf zu lesen.

  2. Wenn recv() -1 zurück, sollten Sie den Fehler melden, die Fassung schließen, und aufhören zu lesen, es sei denn Sie eine Lese Timeout gesetzt hatte und errno war EAGAIN/EWOULDBLOCK, in welchem ​​Fall Sie jedoch das Timeout behandeln sollte, ist geeignet für Ihre Bewerbung.

+0

Warum # 1 ist ein Fehler? Ich dachte, dass, wenn recv 0 zurückgibt, es keine Daten mehr zu lesen gibt und ich socker schließen und den Puffer zurückgeben kann. In Bezug auf # 2 melde ich einen Fehler in der Fehlerfunktion und exit das Programm Ich bin mir nicht sicher, ob ich verstehe, was du über EAGAIN/EWOULDBLOCK geschrieben hast ... – Artium

Verwandte Themen