Contoh C sederhana dalam melakukan HTTP POST dan memakan respons

90

Saya ingin membuat aplikasi C yang sangat sederhana yang melakukan posting HTTP. Ini akan mengambil beberapa parameter, dan menggunakannya untuk membuat URL. Saya hanya ingin melakukan HTTP POST sederhana dan mendapatkan respons tanpa menggunakan curl (pustaka tidak dan tidak akan diinstal pada mesin yang perlu dijalankan ini).

Kode semu:

  1. Proses 2 argumen

  2. Masukkan args ke dalam URL kerangka: http://api.somesite.com/apikey=ARG1&command=ARG2

  3. Lakukan POST pada URL yang dihasilkan

  4. Konsumsi respons

Pencarian Google dan SO saya belum menghasilkan apa-apa tentang masalah ini.

kmarks2
sumber
2
Apakah Anda menggunakan kerangka jaringan apa pun? OS apa yang Anda gunakan?
cnicutar
Ini hanya akan menjadi kotak Fedora atau Cent dasar. Kerangka kerja jaringan biasanya sys / socket, netdb, arpa / inet. Tidak hanya libcurl.
kmarks2
1
Bukan libcurl. Apakah Anda bersedia menggunakan library lain atau harus semua-POSIX.
cnicutar
Semua POSIX sayangnya. Itu harus benar-benar berdiri bebas di sistem apa pun.
kmarks2
2
Saya memiliki sampel yang saya buat untuk Anda tetapi saya tidak mengerti mengapa Anda menggunakan POST jika tidak ada isi untuk pesan tersebut. Jika semua parameter ada dalam string kueri, mengapa Anda tidak ingin melakukan GET?
Jerry Jeremiah

Jawaban:

191

Pesan memiliki bagian header dan badan pesan yang dipisahkan oleh baris kosong. Baris kosong SELALU diperlukan meskipun tidak ada badan pesan. Header dimulai dengan sebuah perintah dan memiliki baris tambahan dari pasangan nilai kunci yang dipisahkan oleh titik dua dan spasi. Jika ada badan pesan, bisa apa saja yang Anda inginkan.

Garis di header dan baris kosong di akhir header harus diakhiri dengan carraige return dan pasangan linefeed (lihat gaya jeda baris header HTTP ) jadi itulah mengapa baris tersebut memiliki \ r \ n di akhir.

URL memiliki bentuk http://host:port/path?query_string

Ada dua cara utama untuk mengirimkan permintaan ke situs web:

  • GET: String kueri bersifat opsional, tetapi jika ditentukan, harus cukup pendek. Karena itu, header hanya bisa menjadi perintah GET dan tidak ada yang lain. Contoh pesan dapat berupa:

    GET /path?query_string HTTP/1.0\r\n
    \r\n
    
  • POST: Apa yang biasanya ada di string kueri ada di badan pesan sebagai gantinya. Karena itu, header perlu menyertakan atribut Content-Type: dan Content-Length: serta perintah POST. Contoh pesan dapat berupa:

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

Jadi, untuk menjawab pertanyaan Anda: jika URL yang ingin Anda posting adalah http://api.somesite.com/apikey=ARG1&command=ARG2 maka tidak ada body atau query string dan, akibatnya, tidak ada alasan untuk POST karena ada tidak ada apa-apa untuk dimasukkan ke dalam badan pesan dan karenanya tidak ada yang harus dimasukkan ke dalam Jenis Konten: dan Panjang Konten:

Saya kira Anda bisa POST jika Anda benar-benar ingin. Dalam hal ini pesan Anda akan terlihat seperti:

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

Jadi untuk mengirim pesan, program C perlu:

  • buat soket
  • cari alamat IP
  • buka soketnya
  • kirim permintaan
  • tunggu responnya
  • tutup soketnya

Panggilan kirim dan terima tidak serta merta mengirim / menerima SEMUA data yang Anda berikan - mereka akan mengembalikan jumlah byte yang sebenarnya dikirim / diterima. Terserah Anda untuk memanggil mereka dalam satu lingkaran dan mengirim / menerima sisa pesan.

Apa yang tidak saya lakukan dalam contoh ini adalah pemeriksaan kesalahan nyata apa pun - ketika ada yang gagal, saya langsung keluar dari program. Beri tahu saya jika ini berhasil untuk Anda:

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

Seperti jawaban lain yang ditunjukkan, 4096 byte bukanlah respons yang sangat besar. Saya memilih nomor itu secara acak dengan asumsi bahwa tanggapan atas permintaan Anda akan singkat. Jika bisa besar, Anda memiliki dua pilihan:

  • baca header Content-Length: dari respons dan kemudian secara dinamis mengalokasikan cukup memori untuk menampung seluruh respons.
  • tulis respons ke file saat potongan tiba

Informasi tambahan untuk menjawab pertanyaan yang diajukan di komentar:

Bagaimana jika Anda ingin POST data di badan pesan? Kemudian Anda perlu menyertakan header Content-Type: dan Content-Length:. Content-Length: adalah panjang sebenarnya dari segala sesuatu setelah baris kosong yang memisahkan header dari body.

Berikut adalah contoh yang mengambil argumen baris perintah berikut:

  • tuan rumah
  • Pelabuhan
  • perintah (GET atau POST)
  • jalur (tidak termasuk data kueri)
  • data kueri (dimasukkan ke dalam string kueri untuk GET dan ke dalam tubuh untuk POST)
  • daftar tajuk (Panjang Konten: otomatis jika menggunakan POST)

Jadi, untuk pertanyaan awal Anda akan menjalankan:

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

Dan untuk pertanyaan yang ditanyakan di komentar Anda akan menjalankan:

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

Ini kodenya:

#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 Jeremiah
sumber
Argumen apa yang harus diberikan saat dipanggil?
Santiago Martí Olbrich
Anda harus meneruskan sesuatu yang akan digunakan sebagai apikey sebagai parameter pertama dan sesuatu di parameter kedua yang akan digunakan sebagai perintah. Jika Anda ingin menggunakan string kueri yang sama sekali berbeda maka Anda perlu mengubah format string, jumlah parameter dan pesan penggunaan.
Jerry Jeremiah
2
Kode ini mengeluarkan permintaan HTTP yang salah format. HTTP menetapkan bahwa baris permintaan harus diakhiri oleh carriage-return / line-feed pairs ( \r\n), tetapi kode ini menggunakan feed baris kosong.
John Bollinger
@JohnBollinger Itu sangat benar. Terima kasih telah menunjukkannya. Semoga jawaban yang diedit lebih baik.
Jerry Jeremiah
Ada apa dengan pesan kiriman ini? "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"Saya ingin memposting seperti name = reaz. Ini menanggapi 400 Permintaan Buruk
Reaz Murshed
12

Jawaban Jerry bagus. Namun, itu tidak menangani respons yang besar. Perubahan sederhana untuk menangani ini:

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
sumber
3
Anda bisa saja membuat array respons dalam contoh saya lebih besar. Saya berasumsi dia baru saja mendapatkan kembali beberapa json dan tidak mengunduh file besar tetapi tentu saja bahkan json bisa menjadi megabyte tergantung pada kueri ...
Jerry Jeremiah
1
Saya seorang pemula C dan jawaban Anda mungkin benar. Tapi bisakah Anda menambahkan penjelasan pada jawaban Anda?
boop
2
Ini benar-benar hanya komentar atas jawaban yang diterima, dan tidak boleh dilakukan sebagai upaya terpisah untuk menjawab.
Michael Gaskill
1
Hanya satu hal untuk ditambahkan di sini, ini berfungsi dengan baik namun Anda harus membaca ukuran buffer - 1 byte. Dan untuk melihatnya dengan benar, saya tidak akan menggunakan baris baru dalam pernyataan cetak itu. Akan terlihat seperti ini:bytes = recv(sockfd, response, 1023, 0)
xjsc16x
11

Setelah berminggu-minggu penelitian. Saya datang dengan kode berikut. Saya yakin ini adalah kebutuhan minimum untuk membuat koneksi aman dengan SSL ke server 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;
}

Kode di atas akan menjelaskan secara detail bagaimana membuat koneksi TLS dengan remote server.

Catatan penting : kode ini tidak memeriksa apakah kunci publik ditandatangani oleh otoritas yang valid. Artinya saya tidak menggunakan sertifikat dasar untuk validasi. Jangan lupa untuk menerapkan pemeriksaan ini jika tidak, Anda tidak akan tahu apakah Anda menghubungkan situs web yang benar

Ketika datang ke permintaan itu sendiri. Tidak lebih dari menulis permintaan HTTP dengan tangan.

Anda juga dapat menemukan di bawah tautan ini penjelasan bagaimana menginstal openSSL di sistem Anda, dan bagaimana mengkompilasi kode sehingga menggunakan pustaka aman .

David Gatti
sumber
2
Penjelasan Bagus!
Satyam Koyani
tidak, variabel selanjutnya adalah port, kita sudah terhubung ke port yang benar.
David Gatti
3

Pegangan ditambahkan.
Menambahkan header Host.
Menambahkan dukungan linux / windows, diuji (XP, WIN7).
PERINGATAN: ERROR: "kesalahan segmentasi" jika tidak ada host, jalur, atau port sebagai argumen.

#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
sumber