Socket, HTTP Request, Apache reagiert merkwürdig



  • Compiler: lcc
    Webserver: Apache 2.2.xxx
    System: Windows, 32bit

    Ich benutze ein Socket, welches über die socket() Funktion erstellt wurde.
    Mein Code funktioniert auch, vielmehr hab ich eine Frage wieso folgendes passiert:

    Bei einem kleinen Request:

    strcpy(message, "GET /test.php?test=test HTTP/1.1\n"
                    "User-Agent: Hallo\n"
                    "Host: 192.168.2.100\n"
    				"\r\n\r\n");
    

    brauche ich ca. 12 Anfragen (12 x Request schicken) bis mein Apache (2.2.xxx) reagiert.

    Mein PHP Script sieht so aus (nur zum Testen, es funzt - Notice beiseite).

    <?php
    $handle = fopen("test.txt", "w");
    fputs($handle, $_GET['test']);
    fclose($handle);
    ?>
    

    Bei einem HTTP-GET-Request der größer ist brauche ich wiederum nur eine Anfrage, dann reagiert der Server.

    Meine Frage nun: Ist das ein Problem bei C, Apache, PHP, HTTP - kann mir des nicht erklären. Hatte schonmal jemand so ein Prob?

    Ich lass mich überraschen was Ihr dazu sagt, freue mich auf Antworten.

    Hier der Client Code, wo ich mein Socket erzeuge - wobei der ja funktioniert?!

    #include <stdio.h>
    #include <stdlib.h>
    
    #include <winsock.h>
    
    void exitFailure(char *message) {
    fprintf(stderr, "\n%s\n", message);
    exit(EXIT_FAILURE);
    }
    
    int main () {
    
    /**************
    Vereinbarungen
    ***************/
    
    WORD wVersionRequested;
    WSADATA WSAData;
    SOCKET stc;
    
    struct sockaddr_in server;
    struct hostent *server_info;
    unsigned long server_addr;
    
    char *send_to_port;
    int stp_len;
    
    // default
    char ip[16];
    int port;
    char message[700];
    memset(message, 0, sizeof(message));
    
    /*********************************************
    Abfrage der benötigten Informationen (Host, Port)
    **********************************************/
    /*
    printf("\n\t\tIP: ");
    scanf("%16s", &ip);
    
    printf("\t\tPort: ");
    scanf("%5i", &port);
    
    printf("\n\tMessage: ");
    scanf("%16s", &message);
    */
    
    strcpy(ip, "192.168.2.100");
    port = 80;
    
    strcpy(message, "GET /test.php?test=test HTTP/1.1\n"
                    "User-Agent: Hallo\n"
                    "Host: 192.168.2.100\n"
    				"\r\n\r\n"
    				);
    
    send_to_port = message;
    stp_len = strlen(message);
    
    printf("\n\tIP: [%s]\n\tPort: [%i]\n\tMessage: %s\n", ip, port, message);
    
    wVersionRequested = MAKEWORD(2, 0);
    if (WSAStartup(wVersionRequested, &WSAData) != 0) {
    exitFailure("Fehler bei WSAStartup() aufgetreten.");
    }
    
    if ((int)(stc = socket(AF_INET /* IPv4 */, SOCK_STREAM /* TCP */, 0)) < 0) {
    exitFailure("Fehler bei socket() aufgetreten.");
    }
    
    memset (&server, 0, sizeof(server));
    
    /* Server Informationen eintragen. */
    if ((server_addr = inet_addr(ip)) != INADDR_NONE) {
    memcpy((char *)&server.sin_addr, &server_addr, sizeof(server_addr));
    } else {
    server_info = gethostbyname(ip);
      if (NULL == server_info) {
      exitFailure("Fehler bei gethostbyname() aufgetreten.");
      }
    memcpy((char *)&server.sin_addr, server_info->h_addr, server_info->h_length);
    }
    
    server.sin_family = AF_INET /* IPv4 */;
    server.sin_port = htons(port);
    
    /* Verbindungsaufbau */
    if (connect(stc, (struct sockaddr*)&server, sizeof(server)) < 0) {
    exitFailure("Fehler bei connect() aufgetreten.");
    }
    
    /* Daten übertragen */
    if (send(stc, send_to_port, stp_len, 0) != stp_len) {
    exitFailure("Fehler bei send() aufgetreten.");
    }
    
    /* Garbage aufräumen */
    WSACleanup();
    closesocket(stc);
    
    return EXIT_SUCCESS;
    }
    


  • du könntest schonmal alle \n durch \r\n ersetzen



  • Daran liegts nicht.



  • du musst ein \r\n entfernen



  • Hallo.

    Das kllassische Problem, das du beschreibst. Windows serialisiert deinen Code und seine Ausgaben. Das heisst, dass Windows für so'n paar Bytes noch keinen Finger krumm macht, sondern erstmal sammelt. Innerhalb einer Funktion z.B wird aus

    send(data1);
    send(data2);
    send(data3);

    einfach nur

    send(data);

    nach verlassen der Funktion. Du kannst dein Problem in einen Prozess (evtl. Thread) auslagern und diesen nach dem "Senden" schliessen. Das erzwingt das Senden (höchst effektiv und unelegant). Ansonsten gibt es für viele Fälle ein passendes FLUSH_DasJetzt.

    Gruß

    Lars



  • mach das closesocket mal vor WSAStartup



  • sorry meinte vor WSACleanup



  • Danke für die Antworten.

    Das Problem besteht leider weiterhin, ich habe etwas mit setsockopt() herumgespielt, aber ich bekomms nicht hin, dass er die Daten immer sofort sendet.

    Kennt jemand eine Funktion/Code die/der diesen "Flush" ausführt?

    Momentan bin ich soweit, dass ich jedesmal ein neues Socket anfordern, da dies noch etwas weniger Belastung erzeugt wie extra Threads.

    😕 HeLp 😕



  • mach mal nach dem aufruf von send ein recv mit einem byte, dann kannst du dir sicher sein das der request übermittelt wurde


Anmelden zum Antworten