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 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 sockaddr_in server; struct hostent *host_info; 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 socketsn" ); 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( PF_INET, SOCK_STREAM, 0 ); if( sock < 0 ) { perror( "failed to create socket" ); return; }
## Create struct for connection partner ##
memset( &server, 0, sizeof( server ) ); if( ( addr = inet_addr( host ) ) != INADDR_NONE ) {
*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.
host_info = gethostbyname( host ); if( NULL == host_info ) { fprintf( stderr, "unknown server: %sn", host ); return; } memcpy( (char *) &server.sin_addr, host_info->h_addr, host_info->h_length ); }
Set *server* parameters.
server.sin_family = AF_INET; server.sin_port = htons( HTTP_PORT );
## 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.0nn", 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](http://www.sdm-net.org/data/dev/pushclient.c) or the [Bash Script](http://www.sdm-net.org/data/dev/pushclient.sh). Compile the C programme with `gcc -o pushclient pushclient.c`.
Pero bash usa wget sin wget y sin usar otro programa en bash seria aun mas tardado de realizar