Einfaches C-Beispiel zum Durchführen eines HTTP-POST und zum Konsumieren der Antwort

Lesezeit: 18 Minuten

Benutzeravatar von kmarks2
kmmarks2

Ich möchte eine sehr einfache C-Anwendung erstellen, die einen HTTP-Post ausführt. Es benötigt einige Parameter und verwendet diese, um eine URL zu erstellen. Ich möchte nur einen einfachen HTTP-POST ausführen und die Antwort ohne die Verwendung von curl erhalten (die Bibliotheken sind und werden nicht auf dem Computer installiert, der ausgeführt werden muss).

Pseudo-Code:

  1. Verarbeite 2 Argumente

  2. Fügen Sie Argumente in die Vorlagen-URL ein: http://api.somesite.com/apikey=ARG1&command=ARG2

  3. Führen Sie POST auf der generierten URL durch

  4. Antwort verbrauchen

Meine Google- und SO-Suchen haben nichts zu diesem Thema ergeben.

  • Verwenden Sie irgendeine Art von Netzwerk-Framework? Welches Betriebssystem verwendest du?

    – Cnicutar

    27. Februar 2014 um 18:57 Uhr

  • Es wird nur eine einfache Fedora- oder Cent-Box sein. Die Netzwerk-Frameworks sind die üblichen sys/socket, netdb, arpa/inet. Nur nicht libcurl.

    – kmmarks2

    27. Februar 2014 um 18:58 Uhr

  • Nicht libcurl. Sind Sie bereit, mit einer anderen Bibliothek zu arbeiten, oder muss es nur POSIX sein?

    – Cnicutar

    27. Februar 2014 um 18:59 Uhr


  • Alle POSIX leider. Es muss völlig frei auf jedem System stehen.

    – kmmarks2

    27. Februar 2014 um 19:00 Uhr


  • Ich habe ein Beispiel, das ich für Sie erstellt habe, aber ich verstehe nicht, warum Sie POST verwenden, wenn es keinen Text für die Nachricht gibt. Wenn alle Parameter in der Abfragezeichenfolge enthalten sind, warum möchten Sie kein GET ausführen?

    – Jerry Jeremia

    28. Februar 2014 um 3:05 Uhr

Benutzeravatar von Jerry Jeremiah
Jerry Jeremia

Eine Nachricht besteht aus einem Kopfteil und einem Nachrichtentext, die durch eine Leerzeile getrennt sind. Die Leerzeile wird IMMER benötigt, auch wenn kein Nachrichtentext vorhanden ist. Der Header beginnt mit einem Befehl und enthält zusätzliche Zeilen mit Schlüsselwertpaaren, die durch einen Doppelpunkt und ein Leerzeichen getrennt sind. Wenn es einen Nachrichtentext gibt, kann er beliebig sein.

Zeilen im Header und die Leerzeile am Ende des Headers müssen mit einem Carraige-Return- und Linefeed-Paar enden (siehe HTTP-Header-Zeilenumbruchstil), daher haben diese Zeilen \r\n am Ende.

Eine URL hat die Form http://host:port/path?query_string

Es gibt zwei Möglichkeiten, eine Anfrage an eine Website zu senden:

  • GET: Die Abfragezeichenfolge ist optional, muss aber, falls angegeben, angemessen kurz sein. Aus diesem Grund könnte der Header nur der GET-Befehl sein und sonst nichts. Eine Beispielnachricht könnte lauten:

      GET /path?query_string HTTP/1.0\r\n
      \r\n
    
  • POST: Was normalerweise in der Abfragezeichenfolge enthalten wäre, befindet sich stattdessen im Hauptteil der Nachricht. Aus diesem Grund muss der Header die Attribute Content-Type: und Content-Length: sowie den POST-Befehl enthalten. Eine Beispielnachricht könnte lauten:

      POST /path HTTP/1.0\r\n
      Content-Type: text/plain\r\n
      Content-Length: 12\r\n
      \r\n
      query_string
    

Um Ihre Frage zu beantworten: Wenn die URL, an die Sie POST senden möchten, lautet http://api.somesite.com/apikey=ARG1&command=ARG2 dann gibt es keinen Hauptteil oder keine Abfragezeichenfolge und folglich keinen Grund zum POST, da nichts in den Nachrichtentext und somit auch in den Inhaltstyp: und die Inhaltslänge: nicht eingefügt werden kann:

Ich denke, du könntest POST, wenn du wirklich wolltest. In diesem Fall würde Ihre Nachricht wie folgt aussehen:

POST /apikey=ARG1&command=ARG2 HTTP/1.0\r\n
\r\n

Um die Nachricht zu senden, muss das C-Programm also:

  • eine Steckdose erstellen
  • nach der IP-Adresse suchen
  • Steckdose öffnen
  • senden Sie die Anfrage
  • warte auf die Antwort
  • Schließen Sie die Steckdose

Die Sende- und Empfangsaufrufe senden/empfangen nicht unbedingt ALLE Daten, die Sie ihnen geben – sie geben die Anzahl der tatsächlich gesendeten/empfangenen Bytes zurück. Es liegt an Ihnen, sie in einer Schleife aufzurufen und den Rest der Nachricht zu senden/empfangen.

Was ich in diesem Beispiel nicht getan habe, ist eine echte Fehlerprüfung – wenn etwas fehlschlägt, beende ich einfach das Programm. Lassen Sie mich wissen, ob es für Sie funktioniert:

#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* exit */
#include <unistd.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#include <sys/socket.h> /* socket, connect */
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#include <netdb.h> /* struct hostent, gethostbyname */

void error(const char *msg) { perror(msg); exit(0); }

int main(int argc,char *argv[])
{
    /* first what are we going to send and where are we going to send it? */
    int portno =        80;
    char *host =        "api.somesite.com";
    char *message_fmt = "POST /apikey=%s&command=%s HTTP/1.0\r\n\r\n";

    struct hostent *server;
    struct sockaddr_in serv_addr;
    int sockfd, bytes, sent, received, total;
    char message[1024],response[4096];

    if (argc < 3) { puts("Parameters: <apikey> <command>"); exit(0); }

    /* fill in the parameters */
    sprintf(message,message_fmt,argv[1],argv[2]);
    printf("Request:\n%s\n",message);

    /* create the socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) error("ERROR opening socket");

    /* lookup the ip address */
    server = gethostbyname(host);
    if (server == NULL) error("ERROR, no such host");

    /* fill in the structure */
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);
    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);

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

    /* send the request */
    total = strlen(message);
    sent = 0;
    do {
        bytes = write(sockfd,message+sent,total-sent);
        if (bytes < 0)
            error("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while (sent < total);

    /* receive the response */
    memset(response,0,sizeof(response));
    total = sizeof(response)-1;
    received = 0;
    do {
        bytes = read(sockfd,response+received,total-received);
        if (bytes < 0)
            error("ERROR reading response from socket");
        if (bytes == 0)
            break;
        received+=bytes;
    } while (received < total);

    /*
     * if the number of received bytes is the total size of the
     * array then we have run out of space to store the response
     * and it hasn't all arrived yet - so that's a bad thing
     */
    if (received == total)
        error("ERROR storing complete response from socket");

    /* close the socket */
    close(sockfd);

    /* process response */
    printf("Response:\n%s\n",response);

    return 0;
}

Wie die andere Antwort bereits erwähnte, sind 4096 Bytes keine sehr große Antwort. Ich habe diese Nummer nach dem Zufallsprinzip ausgewählt, in der Annahme, dass die Antwort auf Ihre Anfrage kurz sein würde. Wenn es groß sein kann, haben Sie zwei Möglichkeiten:

  • Lesen Sie den Content-Length: Header aus der Antwort und weisen Sie dann dynamisch genug Speicher zu, um die gesamte Antwort aufzunehmen.
  • Schreiben Sie die Antwort in eine Datei, wenn die Teile ankommen

Zusätzliche Informationen zur Beantwortung der in den Kommentaren gestellten Frage:

Was ist, wenn Sie Daten im Nachrichtentext POSTEN möchten? Dann müssen Sie die Header Content-Type: und Content-Length: einfügen. Die Inhaltslänge: ist die tatsächliche Länge von allem nach der Leerzeile, die den Header vom Body trennt.

Hier ist ein Beispiel, das die folgenden Befehlszeilenargumente verwendet:

  • Gastgeber
  • Hafen
  • Befehl (GET oder POST)
  • Pfad (ohne die Abfragedaten)
  • Abfragedaten (für GET in die Abfragezeichenfolge und für POST in den Hauptteil einfügen)
  • Liste der Header (Content-Length: ist automatisch, wenn POST verwendet wird)

Für die ursprüngliche Frage würden Sie also Folgendes ausführen:

a.out api.somesite.com 80 GET "/apikey=ARG1&command=ARG2"

Und für die in den Kommentaren gestellte Frage würden Sie Folgendes ausführen:

a.out api.somesite.com 80 POST / "name=ARG1&value=ARG2" "Content-Type: application/x-www-form-urlencoded"

Hier ist der Code:

#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* exit, atoi, malloc, free */
#include <unistd.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#include <sys/socket.h> /* socket, connect */
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#include <netdb.h> /* struct hostent, gethostbyname */

void error(const char *msg) { perror(msg); exit(0); }

int main(int argc,char *argv[])
{
    int i;
    
    /* first where are we going to send it? */
    int portno = atoi(argv[2])>0?atoi(argv[2]):80;
    char *host = strlen(argv[1])>0?argv[1]:"localhost";

    struct hostent *server;
    struct sockaddr_in serv_addr;
    int sockfd, bytes, sent, received, total, message_size;
    char *message, response[4096];

    if (argc < 5) { puts("Parameters: <host> <port> <method> <path> [<data> [<headers>]]"); exit(0); }

    /* How big is the message? */
    message_size=0;
    if(!strcmp(argv[3],"GET"))
    {
        message_size+=strlen("%s %s%s%s HTTP/1.0\r\n");        /* method         */
        message_size+=strlen(argv[3]);                         /* path           */
        message_size+=strlen(argv[4]);                         /* headers        */
        if(argc>5)
            message_size+=strlen(argv[5]);                     /* query string   */
        for(i=6;i<argc;i++)                                    /* headers        */
            message_size+=strlen(argv[i])+strlen("\r\n");
        message_size+=strlen("\r\n");                          /* blank line     */
    }
    else
    {
        message_size+=strlen("%s %s HTTP/1.0\r\n");
        message_size+=strlen(argv[3]);                         /* method         */
        message_size+=strlen(argv[4]);                         /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            message_size+=strlen(argv[i])+strlen("\r\n");
        if(argc>5)
            message_size+=strlen("Content-Length: %d\r\n")+10; /* content length */
        message_size+=strlen("\r\n");                          /* blank line     */
        if(argc>5)
            message_size+=strlen(argv[5]);                     /* body           */
    }
    
    /* allocate space for the message */
    message=malloc(message_size);
    
    /* fill in the parameters */
    if(!strcmp(argv[3],"GET"))
    {
        if(argc>5)
            sprintf(message,"%s %s%s%s HTTP/1.0\r\n",
                strlen(argv[3])>0?argv[3]:"GET",               /* method         */
                strlen(argv[4])>0?argv[4]:"/",                 /* path           */
                strlen(argv[5])>0?"?":"",                      /* ?              */
                strlen(argv[5])>0?argv[5]:"");                 /* query string   */
        else
            sprintf(message,"%s %s HTTP/1.0\r\n",
                strlen(argv[3])>0?argv[3]:"GET",               /* method         */
                strlen(argv[4])>0?argv[4]:"/");                /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            {strcat(message,argv[i]);strcat(message,"\r\n");}
        strcat(message,"\r\n");                                /* blank line     */
    }
    else
    {
        sprintf(message,"%s %s HTTP/1.0\r\n",
            strlen(argv[3])>0?argv[3]:"POST",                  /* method         */
            strlen(argv[4])>0?argv[4]:"/");                    /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            {strcat(message,argv[i]);strcat(message,"\r\n");}
        if(argc>5)
            sprintf(message+strlen(message),"Content-Length: %d\r\n",strlen(argv[5]));
        strcat(message,"\r\n");                                /* blank line     */
        if(argc>5)
            strcat(message,argv[5]);                           /* body           */
    }

    /* What are we going to send? */
    printf("Request:\n%s\n",message);

    /* create the socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) error("ERROR opening socket");

    /* lookup the ip address */
    server = gethostbyname(host);
    if (server == NULL) error("ERROR, no such host");

    /* fill in the structure */
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);
    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);

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

    /* send the request */
    total = strlen(message);
    sent = 0;
    do {
        bytes = write(sockfd,message+sent,total-sent);
        if (bytes < 0)
            error("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while (sent < total);

    /* receive the response */
    memset(response,0,sizeof(response));
    total = sizeof(response)-1;
    received = 0;
    do {
        bytes = read(sockfd,response+received,total-received);
        if (bytes < 0)
            error("ERROR reading response from socket");
        if (bytes == 0)
            break;
        received+=bytes;
    } while (received < total);

    /*
     * if the number of received bytes is the total size of the
     * array then we have run out of space to store the response
     * and it hasn't all arrived yet - so that's a bad thing
     */
    if (received == total)
        error("ERROR storing complete response from socket");

    /* close the socket */
    close(sockfd);

    /* process response */
    printf("Response:\n%s\n",response);

    free(message);
    return 0;
}

  • Welche Argumente sollen beim Aufruf übergeben werden?

    – Santiago Martí Olbrich

    10. Juni 2015 um 19:59 Uhr

  • Sie müssen etwas übergeben, das als apikey als erster Parameter verwendet wird, und etwas im zweiten Parameter, das als Befehl verwendet wird. Wenn Sie einen völlig anderen Abfragestring verwenden möchten, müssen Sie den Formatstring, die Anzahl der Parameter und die Verwendungsnachricht ändern.

    – Jerry Jeremia

    10. Juni 2015 um 20:53 Uhr


  • Dieser Code gibt eine fehlerhafte HTTP-Anfrage aus. HTTP gibt an, dass Anforderungszeilen durch Wagenrücklauf/Zeilenvorschub-Paare (\r\n), aber dieser Code verwendet reine Zeilenvorschübe.

    – Johannes Bollinger

    7. August 2015 um 17:55 Uhr

  • @JohnBollinger Das ist sehr wahr. Danke für den Hinweis. Hoffentlich ist die bearbeitete Antwort besser.

    – Jerry Jeremia

    13. August 2015 um 1:10 Uhr

  • Was ist falsch an dieser Post-Nachricht? "POST /variableName=%s&value=%s HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 4\r\n\r\n\r\n" Ich möchte wie name=reaz posten. Es antwortet 400 Bad Request

    – Reaz Murshed

    13. Oktober 2015 um 16:05 Uhr


Benutzeravatar von David Gatti
David Gatti

Nach wochenlanger Recherche. Dabei bin ich auf folgenden Code gekommen. Ich glaube, dass dies das absolute Minimum ist, das benötigt wird, um eine sichere Verbindung mit SSL zu einem Webserver herzustellen.

#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>

#define APIKEY "YOUR_API_KEY"
#define HOST "YOUR_WEB_SERVER_URI"
#define PORT "443"

int main() {

    //
    //  Initialize the variables
    //
    BIO* bio;
    SSL* ssl;
    SSL_CTX* ctx;

    //
    //   Registers the SSL/TLS ciphers and digests.
    //
    //   Basically start the security layer.
    //
    SSL_library_init();

    //
    //  Creates a new SSL_CTX object as a framework to establish TLS/SSL
    //  or DTLS enabled connections
    //
    ctx = SSL_CTX_new(SSLv23_client_method());

    //
    //  -> Error check
    //
    if (ctx == NULL)
    {
        printf("Ctx is null\n");
    }

    //
    //   Creates a new BIO chain consisting of an SSL BIO
    //
    bio = BIO_new_ssl_connect(ctx);

    //
    //  Use the variable from the beginning of the file to create a 
    //  string that contains the URL to the site that you want to connect
    //  to while also specifying the port.
    //
    BIO_set_conn_hostname(bio, HOST ":" PORT);

    //
    //   Attempts to connect the supplied BIO
    //
    if(BIO_do_connect(bio) <= 0)
    {
        printf("Failed connection\n");
        return 1;
    }
    else
    {
        printf("Connected\n");
    }

    //
    //  The bare minimum to make a HTTP request.
    //
    char* write_buf = "POST / HTTP/1.1\r\n"
                      "Host: " HOST "\r\n"
                      "Authorization: Basic " APIKEY "\r\n"
                      "Connection: close\r\n"
                      "\r\n";

    //
    //   Attempts to write len bytes from buf to BIO
    //
    if(BIO_write(bio, write_buf, strlen(write_buf)) <= 0)
    {
        //
        //  Handle failed writes here
        //
        if(!BIO_should_retry(bio))
        {
            // Not worth implementing, but worth knowing.
        }

        //
        //  -> Let us know about the failed writes
        //
        printf("Failed write\n");
    }

    //
    //  Variables used to read the response from the server
    //
    int size;
    char buf[1024];

    //
    //  Read the response message
    //
    for(;;)
    {
        //
        //  Get chunks of the response 1023 at the time.
        //
        size = BIO_read(bio, buf, 1023);

        //
        //  If no more data, then exit the loop
        //
        if(size <= 0)
        {
            break;
        }

        //
        //  Terminate the string with a 0, to let know C when the string 
        //  ends.
        //
        buf[size] = 0;

        //
        //  ->  Print out the response
        //
        printf("%s", buf);
    }

    //
    //  Clean after ourselves
    //
    BIO_free_all(bio);
    SSL_CTX_free(ctx);

    return 0;
}

Der obige Code erklärt detailliert, wie man eine TLS-Verbindung mit einem Remote-Server herstellt.

Wichtiger Hinweis: Dieser Code überprüft nicht, ob der öffentliche Schlüssel von einer gültigen Autorität signiert wurde. Das heißt, ich verwende keine Root-Zertifikate für die Validierung. Vergessen Sie nicht, diese Überprüfung zu implementieren, da Sie sonst nicht wissen, ob Sie die richtige Website verbinden

Wenn es um die Anfrage selbst geht. Es ist nichts anderes, als den HTTP-Request von Hand zu schreiben.

Darunter finden Sie auch Verknüpfung eine Erklärung, wie Sie openSSL in Ihrem System installieren und wie Sie den Code so kompilieren, dass er die verwendet sichere Bibliothek.

  • Schöne Erklärung!

    – Satyam Koyani

    24. Oktober 2016 um 14:54 Uhr

Jerrys Antwort ist großartig. Es verarbeitet jedoch keine großen Antworten. Eine einfache Änderung, um dies zu handhaben:

memset(response, 0, sizeof(response));
total = sizeof(response)-1;
received = 0;
do {
    printf("RESPONSE: %s\n", response);
    // HANDLE RESPONSE CHUCK HERE BY, FOR EXAMPLE, SAVING TO A FILE.
    memset(response, 0, sizeof(response));
    bytes = recv(sockfd, response, 1024, 0);
    if (bytes < 0)
        printf("ERROR reading response from socket");
    if (bytes == 0)
        break;
    received+=bytes;
} while (1); 

  • Sie könnten das Antwortarray in meinem Beispiel einfach vergrößern. Ich ging davon aus, dass er nur etwas JSON zurückbekam und keine riesige Datei herunterlud, aber natürlich kann sogar JSON je nach Abfrage Megabytes sein …

    – Jerry Jeremia

    10. Juni 2015 um 20:47 Uhr


  • Ich bin ein C-Anfänger und Ihre Antwort könnte richtig sein. Aber können Sie Ihrer Antwort bitte eine Erklärung hinzufügen?

    – boop

    11. November 2015 um 4:12 Uhr

  • Dies ist wirklich nur ein Kommentar zur akzeptierten Antwort und sollte nicht als separater Antwortversuch unternommen werden.

    – Michael Gaskill

    5. Juli 2016 um 14:40 Uhr

  • Nur eine Sache, die hier hinzugefügt werden muss, das funktioniert großartig, aber Sie sollten die Größe des Puffers lesen – 1 Byte. Und um es richtig anzuzeigen, würde ich in dieser Druckanweisung keinen Zeilenumbruch verwenden. Sollte so aussehen:bytes = recv(sockfd, response, 1023, 0)

    – xjsc16x

    4. September 2016 um 1:23 Uhr


  • Hier wären die empfangenen Daten eine rohe Antwort, wie analysieren wir die Nachricht/den Inhalt allein?

    – LIJIN-TV

    12. Februar 2021 um 5:52 Uhr

Benutzeravatar von William Desportes
William Desportes

Griff hinzugefügt.
Host-Header hinzugefügt.
Linux / Windows-Unterstützung hinzugefügt, getestet (XP, WIN7).
WARNUNG: FEHLER: “Segmentierungsfehler”, wenn kein Host, Pfad oder Port als Argument angegeben ist.

#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* exit, atoi, malloc, free */
#include <unistd.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#ifdef __linux__ 
    #include <sys/socket.h> /* socket, connect */
    #include <netdb.h> /* struct hostent, gethostbyname */
    #include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#elif _WIN32
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <windows.h>
    #pragma comment(lib,"ws2_32.lib") //Winsock Library

#else

#endif

void error(const char *msg) { perror(msg); exit(0); }

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

    int i;
    struct hostent *server;
    struct sockaddr_in serv_addr;
    int bytes, sent, received, total, message_size;
    char *message, response[4096];
    int portno = atoi(argv[2])>0?atoi(argv[2]):80;
    char *host = strlen(argv[1])>0?argv[1]:"localhost";
    char *path = strlen(argv[4])>0?argv[4]:"https://stackoverflow.com/";
    if (argc < 5) { puts("Parameters: <host> <port> <method> <path> [<data> [<headers>]]"); exit(0); }
    /* How big is the message? */
    message_size=0;
    if(!strcmp(argv[3],"GET"))
    {
                printf("Process 1\n");
        message_size+=strlen("%s %s%s%s HTTP/1.0\r\nHost: %s\r\n");        /* method         */
        message_size+=strlen(argv[3]);                         /* path           */
        message_size+=strlen(path);                         /* headers        */
        if(argc>5)
            message_size+=strlen(argv[5]);                     /* query string   */
        for(i=6;i<argc;i++)                                    /* headers        */
            message_size+=strlen(argv[i])+strlen("\r\n");
        message_size+=strlen("\r\n");                          /* blank line     */
    }
    else
    {
                printf("Process 2\n");
        message_size+=strlen("%s %s HTTP/1.0\r\nHost: %s\r\n");
        message_size+=strlen(argv[3]);                         /* method         */
        message_size+=strlen(path);                            /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            message_size+=strlen(argv[i])+strlen("\r\n");
        if(argc>5)
            message_size+=strlen("Content-Length: %d\r\n")+10; /* content length */
        message_size+=strlen("\r\n");                          /* blank line     */
        if(argc>5)
            message_size+=strlen(argv[5]);                     /* body           */
    }
            printf("Allocating...\n");
    /* allocate space for the message */
    message=malloc(message_size);

    /* fill in the parameters */
    if(!strcmp(argv[3],"GET"))
    {
        if(argc>5)
            sprintf(message,"%s %s%s%s HTTP/1.0\r\nHost: %s\r\n",
                strlen(argv[3])>0?argv[3]:"GET",               /* method         */
                path,                                          /* path           */
                strlen(argv[5])>0?"?":"",                      /* ?              */
                strlen(argv[5])>0?argv[5]:"",host);            /* query string   */
        else
            sprintf(message,"%s %s HTTP/1.0\r\nHost: %s\r\n",
                strlen(argv[3])>0?argv[3]:"GET",               /* method         */
                path,host);                                    /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            {strcat(message,argv[i]);strcat(message,"\r\n");}
        strcat(message,"\r\n");                                /* blank line     */
    }
    else
    {
        sprintf(message,"%s %s HTTP/1.0\r\nHost: %s\r\n",
            strlen(argv[3])>0?argv[3]:"POST",                  /* method         */
            path,host);                                        /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            {strcat(message,argv[i]);strcat(message,"\r\n");}
        if(argc>5)
            sprintf(message+strlen(message),"Content-Length: %d\r\n",(int)strlen(argv[5]));
        strcat(message,"\r\n");                                /* blank line     */
        if(argc>5)
            strcat(message,argv[5]);                           /* body           */
    }
    printf("Processed\n");
    /* What are we going to send? */
    printf("Request:\n%s\n",message);
        /* lookup the ip address */

    total = strlen(message);
    /* create the socket */
    #ifdef _WIN32
WSADATA wsa;
SOCKET s;

printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
    printf("Failed. Error Code : %d",WSAGetLastError());
    return 1;
}

printf("Initialised.\n");

//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
    printf("Could not create socket : %d" , WSAGetLastError());
}

printf("Socket created.\n");

server = gethostbyname(host);
serv_addr.sin_addr.s_addr = inet_addr(server->h_addr);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
//Connect to remote server
if (connect(s , (struct sockaddr *)&serv_addr , sizeof(serv_addr)) < 0)
{
    printf("connect failed with error code : %d" , WSAGetLastError());
    return 1;
}

puts("Connected");
if( send(s , message , strlen(message) , 0) < 0)
{
    printf("Send failed with error code : %d" , WSAGetLastError());
    return 1;
}
puts("Data Send\n");

//Receive a reply from the server
if((received = recv(s , response , 2000 , 0)) == SOCKET_ERROR)
{
    printf("recv failed with error code : %d" , WSAGetLastError());
}

puts("Reply received\n");

//Add a NULL terminating character to make it a proper string before printing
response[received] = '\0';
puts(response);

closesocket(s);
WSACleanup();
    #endif
    #ifdef __linux__ 
    int sockfd;
    server = gethostbyname(host);
    if (server == NULL) error("ERROR, no such host");
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) error("ERROR opening socket");
        /* fill in the structure */
        memset(&serv_addr,0,sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(portno);
        memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
                /* connect the socket */
        if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
            error("ERROR connecting");
                /* send the request */

    sent = 0;
    do {
        bytes = write(sockfd,message+sent,total-sent);
        if (bytes < 0)
            error("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while (sent < total);
    /* receive the response */
    memset(response, 0, sizeof(response));
    total = sizeof(response)-1;
    received = 0;
    printf("Response: \n");
    do {
       printf("%s", response);
       memset(response, 0, sizeof(response));
       bytes = recv(sockfd, response, 1024, 0);
        if (bytes < 0)
           printf("ERROR reading response from socket");
       if (bytes == 0)
           break;
       received+=bytes;
    } while (1);

    if (received == total)
        error("ERROR storing complete response from socket");

    /* close the socket */
    close(sockfd);
    #endif


    free(message);

    return 0;
}

1422430cookie-checkEinfaches C-Beispiel zum Durchführen eines HTTP-POST und zum Konsumieren der Antwort

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy