Exemple C simple de faire un HTTP POST et de consommer la réponse

90

Je voudrais créer une application C très simple qui fait un message HTTP. Il faudra quelques paramètres et les utiliser pour construire une URL. Je voudrais juste faire un simple HTTP POST et obtenir la réponse sans utiliser curl (les bibliothèques ne sont pas et ne seront pas installées sur la machine à exécuter).

Pseudo-code:

  1. Processus 2 arguments

  2. Placez les arguments dans l'URL du modèle: http://api.somesite.com/apikey=ARG1&command=ARG2

  3. Faire un POST sur l'URL générée

  4. Consommer la réponse

Mes recherches Google et SO n'ont rien donné à ce sujet.

kmarks2
la source
2
Utilisez-vous un type de framework réseau? Quel OS utilisez-vous?
cnicutar le
Ce sera juste une boîte Fedora ou Cent. Les frameworks réseau sont les habituels sys / socket, netdb, arpa / inet. Mais pas libcurl.
kmarks2
1
Pas libcurl. Êtes-vous prêt à utiliser une autre bibliothèque ou doit-elle être entièrement POSIX.
cnicutar
Tous les POSIX malheureusement. Il doit être complètement autonome sur n'importe quel système.
kmarks2
2
J'ai un échantillon que j'ai fait pour vous mais je ne comprends pas pourquoi vous utilisez POST s'il n'y a pas de corps pour le message. Si tous les paramètres sont dans la chaîne de requête, pourquoi ne voulez-vous pas faire un GET?
Jerry Jeremiah

Réponses:

191

Un message a une partie d'en-tête et un corps de message séparés par une ligne vide. La ligne vide est TOUJOURS nécessaire même s'il n'y a pas de corps de message. L'en-tête commence par une commande et comporte des lignes supplémentaires de paires valeur / clé séparées par deux points et un espace. S'il y a un corps de message, il peut s'agir de tout ce que vous voulez.

Les lignes dans l'en-tête et la ligne vide à la fin de l'en-tête doivent se terminer par un retour carraige et une paire de saut de ligne (voir Style de saut de ligne d'en-tête HTTP ), c'est pourquoi ces lignes ont \ r \ n à la fin.

Une URL a la forme de http://host:port/path?query_string

Il existe deux façons principales de soumettre une demande à un site Web:

  • GET: la chaîne de requête est facultative mais, si elle est spécifiée, doit être raisonnablement courte. Pour cette raison, l'en-tête pourrait simplement être la commande GET et rien d'autre. Un exemple de message pourrait être:

    GET /path?query_string HTTP/1.0\r\n
    \r\n
    
  • POST: Ce qui serait normalement dans la chaîne de requête se trouve à la place dans le corps du message. Pour cette raison, l'en-tête doit inclure les attributs Content-Type: et Content-Length: ainsi que la commande POST. Un exemple de message pourrait être:

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

Donc, pour répondre à votre question: si l'URL sur laquelle vous souhaitez POSTER est http://api.somesite.com/apikey=ARG1&command=ARG2 alors il n'y a pas de corps ou de chaîne de requête et, par conséquent, aucune raison de POSTER car il il n'y a rien à mettre dans le corps du message et donc rien à mettre dans Content-Type: et Content-Length:

Je suppose que vous pourriez POSTER si vous le vouliez vraiment. Dans ce cas, votre message ressemblerait à:

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

Donc, pour envoyer le message, le programme C doit:

  • créer une prise
  • rechercher l'adresse IP
  • ouvrir la prise
  • envoyer la demande
  • attend la réponse
  • ferme la prise

Les appels d'envoi et de réception n'enverront / ne recevront pas nécessairement TOUTES les données que vous leur fournissez - ils renverront le nombre d'octets réellement envoyés / reçus. C'est à vous de les appeler en boucle et d'envoyer / recevoir le reste du message.

Ce que je n'ai pas fait dans cet exemple, c'est une sorte de vérification d'erreur réelle - quand quelque chose échoue, je quitte simplement le programme. Dites-moi si cela marche pour vous:

#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 (received == total)
        error("ERROR storing complete response from socket");

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

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

    return 0;
}

Comme l'autre réponse l'a souligné, 4096 octets n'est pas une très grande réponse. J'ai choisi ce nombre au hasard en supposant que la réponse à votre demande serait courte. Si cela peut être gros, vous avez deux choix:

  • lisez l'en-tête Content-Length: de la réponse, puis allouez dynamiquement suffisamment de mémoire pour contenir toute la réponse.
  • écrire la réponse à un fichier au fur et à mesure que les pièces arrivent

Informations complémentaires pour répondre à la question posée dans les commentaires:

Que faire si vous souhaitez POSTER des données dans le corps du message? Ensuite, vous devez inclure les en-têtes Content-Type: et Content-Length:. Le Content-Length: est la longueur réelle de tout après la ligne vide qui sépare l'en-tête du corps.

Voici un exemple qui prend les arguments de ligne de commande suivants:

  • hôte
  • Port
  • commande (GET ou POST)
  • chemin (sans les données de la requête)
  • données de requête (insérées dans la chaîne de requête pour GET et dans le corps pour POST)
  • liste des en-têtes (Content-Length: est automatique si vous utilisez POST)

Donc, pour la question d'origine, vous exécuteriez:

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

Et pour la question posée dans les commentaires, vous exécuteriez:

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

Voici le 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 (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;
}
Jerry Jérémie
la source
Quels arguments doivent être passés lors de l'appel?
Santiago Martí Olbrich
Vous devez passer quelque chose qui sera utilisé comme apikey comme premier paramètre et quelque chose dans le deuxième paramètre qui sera utilisé comme commande. Si vous souhaitez utiliser une chaîne de requête complètement différente, vous devez modifier la chaîne de format, le nombre de paramètres et le message d'utilisation.
Jerry Jeremiah
2
Ce code émet une requête HTTP malformée. HTTP spécifie que les lignes de demande doivent être terminées par des paires retour chariot / saut de ligne ( \r\n), mais ce code utilise des sauts de ligne nus.
John Bollinger
@JohnBollinger C'est très vrai. Merci de l'avoir signalé. Espérons que la réponse modifiée est meilleure.
Jerry Jeremiah
Quel est le problème avec ce message? "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"Je veux publier comme name = reaz. Il répond à 400 Bad Request
Reaz Murshed
12

La réponse de Jerry est excellente. Cependant, il ne gère pas les réponses volumineuses. Un simple changement pour gérer cela:

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); 
Peter Washington
la source
3
Vous pouvez simplement agrandir le tableau de réponses de mon exemple. Je supposais qu'il récupérait juste du json et qu'il ne téléchargeait pas un fichier énorme, mais bien sûr, même json peut être mégaoctets en fonction de la requête ...
Jerry Jeremiah
1
Je suis un débutant en C et votre réponse est peut-être correcte. Mais pouvez-vous s'il vous plaît ajouter une explication à votre réponse?
boop
2
Il ne s'agit en réalité que d'un commentaire sur la réponse acceptée et n'aurait pas dû être fait comme une tentative distincte de réponse.
Michael Gaskill
1
Juste une chose à ajouter ici, cela fonctionne très bien, mais vous devriez lire la taille du tampon - 1 octet. Et pour l'afficher correctement, je n'utiliserais pas de nouvelle ligne dans cette instruction d'impression. Devrait ressembler à ceci:bytes = recv(sockfd, response, 1023, 0)
xjsc16x
11

Après des semaines de recherche. Je suis venu avec le code suivant. Je pense que c'est le strict minimum nécessaire pour établir une connexion sécurisée avec SSL à un serveur Web.

#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;
}

Le code ci-dessus expliquera en détail comment établir une connexion TLS avec un serveur distant.

Remarque importante : ce code ne vérifie pas si la clé publique a été signée par une autorité valide. Cela signifie que je n'utilise pas de certificats racine pour la validation. N'oubliez pas de mettre en œuvre cette vérification sinon vous ne saurez pas si vous connectez le bon site Web

Quand il s'agit de la demande elle-même. Ce n'est rien de plus qu'écrire la requête HTTP à la main.

Vous pouvez également trouver sous ce lien une explication comment installer openSSL dans votre système et comment compiler le code afin qu'il utilise la bibliothèque sécurisée .

David Gatti
la source
2
Belle explication!
Satyam Koyani
non, la variable suivante est le port, nous nous connectons déjà au bon port.
David Gatti
3

Poignée ajoutée.
En-tête d'hôte ajouté.
Ajout du support Linux / Windows, testé (XP, WIN7).
AVERTISSEMENT: ERREUR: "erreur de segmentation" si aucun hôte, chemin ou port en argument.

#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]:"/";
    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;
}
William Desportes
la source