HTTP Push Client in Posix C

Have you ever wanted to push a value to a HTTP page and don’t care about the result? Well, you can do it in pure C, but be prepared - it is not as trivial as you might think. Here is how to do it.

Includes

#include #include #include #include

Distinguish Windows from Unix/Linux

We need to include winsock if we compile under Windows - otherwise use Unix/Linux headers for networking operations.

#ifdef _WIN32 #include #include #else #include #include #include #include #define closesocket(s) close(s) #endif

Defining the port to connect to

The default port to connect to is 80. You can change it here if you need to.

#define HTTP_PORT 80

The push_value Function

void push_value( char *host, char *path, char *value ) {

Variable Declarations

time_t tt;

This is the place to save the actual date string to. It’s length is limited to 15 characters - 14 for the date string and one for the terminating \0 at the end.

char datum[15];

The actual HTTP Request is being written to this variable.

char request[300];

These are needed to create the socket/connection.

struct sockaddrin server; struct hostent *hostinfo; unsigned long addr; int sock;

Windows needs Winsock initialisation

Windows TCP initialisation has to be done only if compiled under Windows.

#ifdef _WIN32 short wVersReq; WSADATA wsaData; wVersReq = MAKEWORD( 1, 1 ); if( WSAStartup( wVersReq, &wsaData ) != 0 ) { fprintf( stderr, “Failed to init windows sockets\n” ); return; } #endif

Get actual date

strftime creates the actual date into datum, it uses the format given (“%Y%m%d%H%M%S”) and the current time from time(NULL).

tt = time(NULL); strftime( datum, sizeof( datum ), “%Y%m%d%H%M%S”, localtime(&tt) );

Create a socket

sock = socket( PFINET, SOCKSTREAM, 0 ); if( sock < 0 ) { perror( “failed to create socket” ); return; }

Create struct for connection partner

memset( &server, 0, sizeof( server ) ); if( ( addr = inetaddr( host ) ) != INADDRNONE ) {

host is a numerical IP Address. Nothing special has to be done.

memcpy( (char *) &server.sin_addr, &addr, sizeof( addr ) ); } else {

host is a domain name. Convert this domain name into a numerical IP Address.

hostinfo = gethostbyname( host ); if( NULL == hostinfo ) { fprintf( stderr, “unknown server: %s\n”, host ); return; } memcpy( (char *) &server.sinaddr, hostinfo->haddr, hostinfo->h_length ); }

Set server parameters.

server.sinfamily = AFINET; server.sinport = htons( HTTPPORT );

Create connection with partner

Time to get together. Creating connection to server.

if( connect( sock, (struct sockaddr*) &server, sizeof( server ) ) < 0 ) { perror( “can’t connect to server” ); return; }

Create HTTP 1.0 request with given value value and current time datum.

sprintf( request, “GET %s?value=%s&time=%s HTTP/1.0\n\n”, path, value, datum);

Send created HTTP request to server. Ignore response, as it is not needed (see specification).

send( sock, request, sizeof( request ), 0 );

Close socket, we don’t need it anymore - “fire and forget”.

closesocket( sock ); }

Call push_value

This is a small main function that gets the host, path and value from the command line and calls the push_value function. Originally for testing purpose only, but I left it in for you to test it on your own.

int main( int argc, char **argv ) { if( argc < 3 ) { fprintf( stderr, “usage: %s host path value”, argv[0] ); return -1; } push_value( argv[1], argv[2], argv[3] ); return 0; }

Conclusion

With a shell script it would have been a lot easier. Given the above C programme we could create an equivalent bash shell script to do that:

#!/bin/sh if [ $# -lt 3 ]; then echo “usage: $0 host path value” exit -1 fi TIME=$(date +%Y%m%d%H%M%S) wget -q -O /dev/null “http://$1:80$2?value=$3&time=$TIME”

On the other hand this shell script takes about twice the time to complete than the C programme. Decide for yourself if it’s worth the cost.

If you like you can download the C Source Code or the Bash Script. Compile the C programme with gcc -o pushclient pushclient.c.

0 Responses to “HTTP Push Client in Posix C”


  1. No Comments

Leave a Reply