Sneaky Pete redux --#-- Our first step is to rewrite Sneaky Pete, the Java HTTP client, in C.

paul.c will need to do two special things: Formulate a request header and POST string, and open an Internet socket on a server. Because this is C, both will take a moderate amount of code to perform.

We want to start with opening a socket. Creating the socket is the simplest part. A call to the socket function needs three parameters: an int constant representing the Internet member of address families (AF_INET), another int constant representing a bi-directional stream (SOCK_STREAM), and a protocol identifier, which is always zero for stream sockets on Internet addresses.

#include int sock; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) die("Can't open socket\n");
You'll need to define a Perl-style die function somewhere:

void die(char *s) { printf("%s\n", s); exit(0); }
Next, you open a connection on a specific port to the target host. But before you do, you need to set up an Internet socket address structure defined in the header file netinet/in.h. And to do that, you need:

long ipAddress; struct hostent* hostInfo; struct sockaddr_in sockInfo; int sock; // Fill sock address structure memset(&sockInfo, 0, sizeof(sockInfo)); sockInfo.sin_family = AF_INET; sockInfo.sin_port = htons(port); ipAddress = inet_addr(host); if (ipAddress < 0) { hostInfo = gethostbyname(host); ipAddress = *(long *)*hostInfo->h_addr_list; } sockInfo.sin_addr.s_addr = ipAddress;
The Internet socket address structure (struct sockaddr_in) needs three values: the Internet address cast as a single 32-bit number, the port and the AF_INET constant. (The port number is first passed through the macro htons defined in netinet/in.h. htons, for host-to-network-short, swaps the value's byte order from the host (Little Endian on Intel machines) to network byte order (Big Endian)). It's important to fill the struct w/ NULLs first, though, because there is more space in it that must be zeroes if not used.

The function inet_addr() will cast a dotted quad Internet address to a 32-bit integer. But if the host string is a fully-qualified domain (i.e., www.darkspell.com), inet_addr() will return -1. In that case you need to call gethostbyname.

This involves a tricky type cast. gethostbyname stuffs the address into a four-char array in a hostent record (defined in netdb.h). The hostent record itself is accessed via a pointer. So, to obtain the Internet address as a 32-bit number, you need to cast the pointer to the four-char array to a pointer to a long, and dereference the long.

Then, just assign it to the sin_addr.s_addr member of the sockaddr_in struct and we're ready to go.