2016-06-02 8 views
-1

Ich habe eine Aufgabe, einen http-Server in c-Code zu implementieren. es sollte die Behandlung mehrerer Verbindungen enthalten, aber für jetzt möchte ich nur sicherstellen, dass es mit nur einer einzigen Verbindung funktioniert. erste, hier ist mein Code:HTTP-Server (c) - senden Befehl funktioniert nicht (leere Antwort vom Server)

#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 

#define BUF_SIZE 1025 

int main(int argc, char **argv) 
{ 

    uint16_t portNum = 80; 
    int connfd = 0, listenFd; 
    struct sockaddr_in serv_addr, peer_addr; 

    if ((listenFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     printf("socket syscall failed: %s.\nExiting...\n", strerror(errno)); 
     exit(EXIT_FAILURE); 
    } 
    memset(&serv_addr, 0, sizeof(serv_addr)); 


    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    serv_addr.sin_port = htons(portNum); 

    if (bind(listenFd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) 
    { 
     printf("bind syscall failed: %s\nExiting...\n", strerror(errno)); 
     exit(EXIT_FAILURE); 
    } 

    if (listen(listenFd, 5)) 
    { 
     printf("listen syscall failed: %s\nExiting...\n", strerror(errno)); 
     exit(EXIT_FAILURE); 
    } 

    while (1) 
    { 
     /* new connection */ 
     socklen_t addrsize = sizeof(struct sockaddr_in); 
     connfd = accept(listenFd, (struct sockaddr *) &peer_addr, &addrsize); 
     if (connfd < 0) 
     { 
      printf("\n Error : Accept Failed. %s \n", strerror(errno)); 
      return 1; 
     } 

     char httpRequest[BUF_SIZE] = {0};  
     if ((recv(connfd, httpRequest, BUF_SIZE, 0)) == -1) 
     { 
      printf("recv syscall failed: %s\nExiting...\n", strerror(errno)); 
      exit(EXIT_FAILURE); 
     } 

     char msg[BUF_SIZE] = {0}; 
     strcpy(msg, "200 OK THIS IS A TEST"); 
     printf("sending message...\n"); 
     int len = strlen(msg); 
     if (send(connfd, msg, len, 0) < 0) 
     { 
      printf("SEND ERROR\n"); 
      exit(EXIT_FAILURE); 
     } 
     printf("message sent!\n"); 
     close(connfd); 
     close(listenFd); 
     // THIS IS FOR DEBUG - ignore... 
     return 0; 

    } 

    return EXIT_SUCCESS; 
} 

hier ist mein Problem: meinen Code zu testen ich den folgenden Befehl in einem anderen Linux-Terminal lief:

curl -v loaclhost:80/~/ex.txt 

(wo ex.txt einfach ist ein Test Datei ...) hier ist das Problem: Ich sehe die HTTP-Anfrage sowohl in den Server und in der Curl-Ausgabe, aber es scheint, wie der Befehl "Senden" des Servers nicht funktioniert - im Curl-Fenster unter der http rquest heißt es:

* Empty reply from server 
* Connection #0 to host localhost left intact 
curl: (52) Empty reply from server 

irgendwelche ideen?

+0

'listenFd',' maxRequests', 'peer_addr' und' BUF_SIZE' ist nicht angemeldet . Erforderliche Header fehlen ebenfalls. Warum veröffentlichen Sie kein [minimales, vollständiges und verifizierbares Beispiel] (http://stackoverflow.com/help/mcve)? – MikeCAT

+0

gerade repariert es ... es ist nicht die Hauptsache, sowieso ... jetzt könnte die alles, was Sie brauchen, um mich zu helfen. Ich hoffe ... -_- – noamgot

+0

Hmmm, konnte nicht auf meinem Raspberry Pi mit dem Ändern von 'uint16_t portNum = 80; 'nach' uint16_t portNum = 8098; 'reproduzieren, so dass es keine Root-Übertragung zum Binden benötigt. – MikeCAT

Antwort

1
  1. Puffer von 1024 ist zu klein für etwas ernstes. Für nur lokal spielen funktioniert es OK. Wenn Sie jemals einen ernsthaften Arbeitspuffer von 8192 Bytes machen wollen, funktioniert das auch für schwere Lasten.

  2. recv() blockiert in den meisten Implementierungen, was bedeutet, dass es blockieren wird, bis es die eingegebene Anzahl von Bytes empfängt oder ein Client die Verbindung nach dem Senden von Daten schließt. Ich habe nicht gesehen, dass Ihr Socket definiert und als nicht blockierend behandelt wird. So ist dieser Teil bis zur Locke zu überwinden.

  3. Ihre HTTP-Antwort ist falsch.

Der Header sollte wie folgt aussehen:

"HTTP/1.1 200 OK\r\nStatus: 200 OK\r\nContent-Type: text/plain\r\n\r\n" 

Sie können auch einen Header hinzufügen:

"Content-Length: 0" 

wie Sie keine Daten zurück, außer dem Header zu senden sind.

Wenn Sie weiterhin HTTP/0.9 verwenden oder zu HtTP/1.0 wechseln, sollten Sie die Verbindung mit einem Client schließen, nachdem Sie die Daten an ihn gesendet haben.

HTTP/1.1 unterstützt die geöffnete Verbindung, wird jedoch normalerweise über Keep-Alive und Connection-Header gesteuert.

+0

Die HTTP-Antwort ist nicht falsch, wenn Ihr Server nur das HTTP/0.9-Protokoll unterstützt. Siehe [RFC1945] (https://www.ietf.org/rfc/rfc1945.txt) 6. Antwort. 'Simple-Response' enthält nur' [Entity-Body] '. – MikeCAT

+0

ist mir egal. Es ist falsch, weil es nicht in \ r \ n \ r \ n endet. Da es keine Header enthält, fragen die Clients unabhängig von der Protokollnummer. Und weil das Auslassen der Protokollversion nicht notwendigerweise garantiert, dass neue Kunden es überhaupt mögen würden. 0,9 ist veraltet. Auch, weil etwas der Spezifikation entspricht, bedeutet es nicht, dass es funktioniert. Ich habe schon einmal HTTP-Server geschrieben, also glauben Sie mir, es ist ein Durcheinander ohne Ende, wenn es darum geht, was sein sollte und was es in der realen Welt ist. – Dalen

+0

@Dalen dies ist nur ein Stück Code, ich bin nur herumalbern - ich weiß, das ist keine vollständige HTTP-Antwort. Das eigentliche Problem war, dass ich die Zeichenfolge nicht mit einem '\ n' – noamgot

-2

ok, -1 für mich, es hat nicht funktioniert aufgrund des '\ n' Charakter in strcpy fehlt ..

+0

hey, ich meinte nicht literally! :( – noamgot

Verwandte Themen