HTTPPOSTを実行して応答を消費する単純なCの例


90

HTTPPOSTを実行する非常に単純なCアプリケーションを作成したいと思います。いくつかのパラメーターを取り、これらを使用してURLを作成します。単純なHTTPPOSTを実行し、curlを使用せずに応答を取得したいと思います(ライブラリは、これを実行する必要のあるマシンにインストールされておらず、インストールされません)。

擬似コード:

  1. 2つの引数を処理します

  2. テンプレートURLに引数を入力します:http//api.somesite.com/apikey=ARG1&command=ARG2

  3. 生成されたURLでPOSTを実行します

  4. 応答を消費する

私のグーグルとSOの検索はこの問題に関して何ももたらさなかった。


2
どんな種類のネットワークフレームワークを使用していますか?どのOSを使用していますか?
cnicutar 2014

基本的なFedoraまたはCentボックスになります。ネットワークフレームワークは、通常のsys / socket、netdb、arpa / inetです。libcurlではありません。
kmarks2 2014

1
libcurlではありません。他のライブラリを使用してもかまいませんか、それともすべてPOSIXである必要がありますか。
cnicutar 2014

残念ながら、すべてのPOSIX。どのシステムでも完全に自立している必要があります。
kmarks2 2014

2
サンプルを作成しましたが、メッセージの本文がないのにPOSTを使用している理由がわかりません。すべてのパラメータがクエリ文字列に含まれている場合、GETを実行しないのはなぜですか?
ジェリージェレマイア

回答:


191

メッセージには、ヘッダー部分とメッセージ本文が空白行で区切られています。メッセージ本文がない場合でも、空白行は常に必要です。ヘッダーはコマンドで始まり、コロンとスペースで区切られたキーと値のペアの追加行があります。メッセージ本文がある場合、それはあなたが望むものなら何でもかまいません。

ヘッダーの行とヘッダーの最後の空白行は、carraige returnとlinefeedのペアで終了する必要がありますHTTPヘッダーの改行スタイルを参照)。そのため、これらの行の最後には\ r \ nがあります。

URLの形式は次のとおりです。 http://host:port/path?query_string

Webサイトにリクエストを送信するには、主に2つの方法があります。

  • GET:クエリ文字列はオプションですが、指定する場合は、適度に短くする必要があります。このため、ヘッダーはGETコマンドであり、他には何もありません。サンプルメッセージは次のとおりです。

    GET /path?query_string HTTP/1.0\r\n
    \r\n
    
  • POST:通常、クエリ文字列に含まれるのは、代わりにメッセージの本文にあります。このため、ヘッダーには、POSTコマンドだけでなくContent-Type:属性とContent-Length:属性を含める必要があります。サンプルメッセージは次のとおりです。

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

したがって、質問に答えるには、POSTに関心のあるURLがhttp://api.somesite.com/apikey=ARG1&command=ARG2の場合、本文やクエリ文字列がないため、POSTする理由はありません。メッセージの本文に入れるものは何もないので、Content-Type:とContent-Length:に入れるものは何もありません。

本当にやりたいのならPOSTできると思います。その場合、メッセージは次のようになります。

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

したがって、メッセージを送信するには、Cプログラムは次のことを行う必要があります。

  • ソケットを作成する
  • IPアドレスを検索する
  • ソケットを開きます
  • リクエストを送信する
  • 応答を待つ
  • ソケットを閉じます

送受信呼び出しは、必ずしも指定したすべてのデータを送受信するわけではありません。実際に送受信されたバイト数を返します。それらをループで呼び出し、メッセージの残りを送受信するのはあなた次第です。

このサンプルで私がしなかったことは、実際のエラーチェックです。何かが失敗したときは、プログラムを終了するだけです。それがあなたのために働くかどうか私に知らせてください:

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

指摘された他の回答のように、4096バイトはそれほど大きな応答ではありません。あなたのリクエストへの応答が短いと仮定して、私はその番号をランダムに選びました。大きくなる可能性がある場合は、2つの選択肢があります。

  • 応答からContent-Length:ヘッダーを読み取り、応答全体を保持するのに十分なメモリを動的に割り当てます。
  • ピースが到着したら、ファイルに応答を書き込みます

コメントで尋ねられた質問に答えるための追加情報:

メッセージの本文にデータをPOSTしたい場合はどうなりますか?次に、Content-Type:ヘッダーとContent-Length:ヘッダーを含める必要があります。Content-Length:ヘッダーと本文を区切る空白行の後のすべての実際の長さです。

次のコマンドライン引数を取るサンプルを次に示します。

  • ホスト
  • ポート
  • コマンド(GETまたはPOST)
  • パス(クエリデータを含まない)
  • クエリデータ(GETの場合はクエリ文字列に、POSTの場合は本文に入力します)
  • ヘッダーのリスト(Content-Length:POSTを使用している場合は自動)

したがって、元の質問に対して実行します。

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

そして、あなたが実行するコメントで尋ねられた質問のために:

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

コードは次のとおりです。

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

呼び出されたときにどの引数を渡す必要がありますか?
サンティアゴマルティオルブリッチ

apikeyとして使用されるものを最初のパラメーターとして渡し、2番目のパラメーターでコマンドとして使用されるものを渡す必要があります。まったく異なるクエリ文字列を使用する場合は、フォーマット文字列、パラメータの数、および使用法メッセージを変更する必要があります。
ジェリージェレマイア2015年

2
このコードは、不正な形式のHTTPリクエストを発行します。HTTPは、要求行をキャリッジリターン/ラインフィードのペア(\r\n)で終了する必要があることを指定していますが、このコードは裸のラインフィードを使用します。
ジョンボリンジャー2015

@JohnBollingerそれは非常に真実です。ご指摘いただきありがとうございます。うまくいけば、編集された答えがより良いです。
ジェリージェレマイア

この投稿メッセージの何が問題になっていますか?"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"name = reazのように投稿したいです。400 Bad Requestに応答します
Reaz Murshed 2015

12

ジェリーの答えは素晴らしいです。ただし、大きな応答は処理しません。これを処理するための簡単な変更:

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); 

3
私の例の応答配列を大きくすることができます。私は彼がちょうどいくつかのjsonを取り戻していて、巨大なファイルをダウンロードしていないと思っていましたが、もちろん、クエリによってはjsonでさえメガバイトになる可能性があります...
Jerry Jeremiah 2015年

1
私はCの初心者ですが、あなたの答えは正しいかもしれません。しかし、あなたの答えに説明を追加していただけますか?
ブープ2015

2
これは実際には受け入れられた回答に対する単なるコメントであり、個別の回答の試みとして行われるべきではありませんでした。
Michael Gaskill 2016

1
ここに追加するのは1つだけです。これはうまく機能しますが、バッファーのサイズ(1バイト)を読み取る必要があります。そしてそれを正しく表示するために、私はそのprintステートメントで改行を使用しません。:次のようになりますbytes = recv(sockfd, response, 1023, 0)
xjsc16x

11

数週間の研究の後。私は次のコードを思いついた。これは、SSLを使用して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;
}

上記のコードは、リモートサーバーとのTLS接続を確立する方法を詳細に説明しています。

重要な注意:このコードは、公開鍵が有効な機関によって署名されているかどうかをチェックしません。つまり、検証にルート証明書を使用しません。このチェックを実装することを忘れないでください。そうしないと、適切なWebサイトに接続しているかどうかがわかりません。

リクエスト自体に関しては。HTTPリクエストを手作業で書くだけです。

また、このリンクの下に、システムにopenSSLをインストールする方法、および安全なライブラリを使用するようにコードをコンパイルする方法の説明があります。


2
いい説明!
Satyam Koyani 2016年

いいえ、次の変数はポートです。すでに正しいポートに接続しています。
David Gatti 2018年

3

ハンドルを追加しました。
ホストヘッダーを追加しました。
Linux / Windowsのサポートを追加し、テスト済み(XP、WIN7)。
警告:エラー:引数としてホスト、パス、またはポートがない場合、「セグメンテーション違反」。

#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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.