Click here to Skip to main content
Licence CPOL
First Posted 13 Feb 2011
Views 6,315
Bookmarked 20 times

Posting to an ASP website via Windows sockets in C

By | 13 Feb 2011 | Article
Posting data to an Internet server made easy with a slick C/C++ class wrapping a call to Windows sockets.

Introduction

Ever needed a quick way to get around to post text to a web server and get a response accordingly? Look no further. In this article, I give the reader a class with two methods for testing the availability of a connection and for posting information.

Background

I use this code to post major text files, line by line, of summaries on PocketPC (Windows Mobile) to a statistical web site via an ASP file.

Using the Code

While under Windows, you can send information on an open socket and read information from the same spot. This is nothing new, but using a socket to post to an internet server can be tricky, especially getting the 'post' syntax absolutely flawless.

As you can see on the header and body text below this paragraph, there is a macro SEND_RQ just for passing clear text values, so do not get misled by any strange char in the C/C++ strings.

#define _DEBUG_PRINT(X)   /* X */
#include <iostream>
#include <string>
#include <stdlib.h>
#include <assert.h>
#include <Winsock2.h>
#define VERSION_MAJOR 1;
#define VERSION_MINOR 1;
#define CRLF "\r\n"    // carriage-return/line feed pair
#define SEND_RQ(MSG) send(sock,MSG, (int) strlen(MSG),0);
using namespace std;
class CHttp
{
public:
    WSADATA                WsaData;
    sockaddr_in            sin;
    size_t                 sock ;
    CHttp(void);
    ~CHttp(void);
    int TestConnectionToHostName (char* hostname);
    int Post (char* hostname, char* api, char* parameters, string& message);
};

#include "StdAfx.h"
#include "CHttp.h"

CHttp::CHttp(void)
{
}
CHttp::~CHttp(void)
{
}
int CHttp::TestConnectionToHostName (char* hostname)
{
    WSAStartup (0x0101, &WsaData);
        sock =  socket(AF_INET, SOCK_STREAM, 0);
        if (sock == -1) 
    {
        return -100;
    }
        sin.sin_family = AF_INET;
        sin.sin_port = htons( (unsigned short)80);
        struct hostent * host_addr = gethostbyname(hostname);
        if(host_addr==NULL) 
    {
        return -101;
        }
        sin.sin_addr.s_addr = *((int*)*host_addr->h_addr_list) ;
        if( connect (sock,(const struct sockaddr *)&sin, sizeof(sockaddr_in) ) == -1 ) 
    {
        return -102;
        }
    WSACleanup( );
    return 0;
}

int CHttp::Post (char* hostname, char* api, char* parameters, string& message)
{
    WSAStartup (0x0101, &WsaData);
        sock =  socket(AF_INET, SOCK_STREAM, 0);
        if (sock == -1) 
    {
        return -100;
    }
        sin.sin_family = AF_INET;
        sin.sin_port = htons( (unsigned short)80);
        struct hostent * host_addr = gethostbyname(hostname);
        if(host_addr==NULL) 
    {
        return -101;
        }
        sin.sin_addr.s_addr = *((int*)*host_addr->h_addr_list) ;

        if( connect (sock,(const struct sockaddr *)&sin, sizeof(sockaddr_in) ) == -1 ) 
    {
        return -102;
    }
    string send_str;
    char content_len[STRING_SIZE_256];
    sprintf(content_len,"Content-Length: %d\r\n",strlen(parameters));
    char host_api[STRING_SIZE_256];
    strcpy(host_api, "http://");
    strcat(host_api, hostname);
    strcat(host_api, api);
    SEND_RQ("POST "); SEND_RQ(host_api); SEND_RQ(" HTTP/1.0\r\n");
    SEND_RQ("From: any@sidegence.com\r\n");
    SEND_RQ("User-Agent: Mozilla/4.0\r\n");
    SEND_RQ("Content-Type: application/x-www-form-urlencoded\r\n");
    SEND_RQ(content_len);
    SEND_RQ("\r\n");
    SEND_RQ(parameters);
    SEND_RQ("\r\n");
    char c1[1];
    int l,line_length;
    bool loop = true;
    bool bHeader = false;
    while(loop) 
    {
        l = recv(sock, c1, 1, 0);
        if(l<0) 
            loop = false;
        if(c1[0]=='\n') 
        {
            if(line_length == 0) 
                loop = false;
            line_length = 0;
            if(message.find("200") != string::npos)
                bHeader = true;
        }
        else 
            if(c1[0]!='\r') 
                line_length++;
        message += c1[0];
    }

     message="";
     if(bHeader) 
     {
         char p[1024];
         while((l = recv(sock,p,1023,0)) > 0)  
            {
                 p[l] = '\0';
                 message += p;
             }
    } 
    else 
    {
        return -103;
    }
    
    int index = (int) message.find("E01");
    if (index>=0) return -104;
    WSACleanup( );
    return 0;
}

The testing method allows the class Client to perceive its readiness to post, that is, it evaluates the presence of a connection - this may be important if working with Windows Mobile, because you may want the application to post only while docking (via USB or whatever) to a connected machine - therefore saving money on internet calls.

If used on an always connected (typically a PC) machine, you may only want to post with a specific schedule, it's up to you.

Points of Interest

I tried many syntaxes for the HTTP POST, and after a careful W3C review, I found that this is the one that works:

SEND_RQ("POST "); SEND_RQ(host_api); SEND_RQ(" HTTP/1.0\r\n");
SEND_RQ("From: any@sidegence.com\r\n");
SEND_RQ("User-Agent: Mozilla/4.0\r\n");
SEND_RQ("Content-Type: application/x-www-form-urlencoded\r\n");
SEND_RQ(content_len);
SEND_RQ("\r\n");
SEND_RQ(parameters);
SEND_RQ("\r\n");

Of course, you will understand the variables better after adding the class to a client project and doing a debug session if you want; the names are fairly descriptive.

After the POST is done, the ASP code is fairly simple; I mean you can just get the QueryString values and parse each variable that reaches the page, process it, and return on the Response object an acknowledgement code return value.

At the end of the method, you can see a 'message' return pattern matching for codes. I used 'E01', etc., to return coding information from the ASP side.

History

  • First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sergio Mach

Software Developer (Senior)

Portugal Portugal

Member

Financial Apps addict since early programming ages;
Statistical Apps writer;
Computer gamming and graphics programmer with a 2 commercial titles: Armor PC/PPC, MidWay XBOX/PC/PPC;
Manic Basketball fan and player;
Traveller;

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Questionhelp PinmemberBISSANN11:56 15 Apr '11  
AnswerRe: help PinmemberDethNile4:56 11 May '11  
Generalvery good Pinmembersd94jimmy17:37 3 Apr '11  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web03 | 2.5.120517.1 | Last Updated 13 Feb 2011
Article Copyright 2011 by Sergio Mach
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid