1. Localhost.c
Here is a commented version of "localhost.c"
// Ignore the includes
#include
#include
#include
#include
main ( )
{
// This is a STRUCTURE returned from "gethostbyname", the reason why it
// doesn't just return a number to represent the address is because
// if we've got a more complex program we may need other info after
// this command, but for our purposes this represents the NUMBER ADDRESS
struct hostent *phe;
// This is the string which stores the NAME ADDRESS of THIS machine
char hostname [ 80 ];
// One of the functions returns an integer to let us know how it
// got on. But we're not checking if it was successful, we're
// assuming, but we still need to catch the return, but it's
// garbage to us. (this is like sscanf() returning the number of arguments it finds)
int stat;
// The NUMBER ADDRESS before the order is reversed (remember big-endian and all that)
long hostip;
// The NUMBER ADDRESS after the order is reversed
long hostiph;
// We initialise the ADDRESS
hostip=0;
// We need to find the ADDRESS of THIS machine, this is what the function below does
// The first parameter is passed by reference, it is an array so no need for (&)
// but we need to let the function know how long this array is so the 80 is put in,
// remember we don't care about "stat"
stat = gethostname (hostname,80);
// Print our NAME ADDRESS
printf ( "hostname is %s; \n ", hostname ) ;
// Here we convert the NAME ADDRESS to NUMBER ADDRESS into the STRUCTURE,
// at the same time checking if it worked
if ((phe=gethostbyname(hostname)) != 0)
{
// Now because the NUMBER ADDRESS is now stored into the "phe" STRUCTURE
// we copy it out. I don't know why we use this function, maybe it's because
// there is extra info we don't need after the 4th byte, anyway we use "bcopy"
// This function copies the NUMBER ADDRESS to "hostip" which is passed by reference
// The last parameter specifies how many bytes we want copied.
bcopy(phe->h_addr,&hostip,4);
// Now we need to change the order of the NUMBER ADDRESS
hostiph = ntohl(hostip);
// Then we print it out as a hexadecimal number (%x)
printf ("host IP address is %x\n ",hostiph );
printf ("\n");
}
// We get here if we couldn't change the NAME ADDRESS to a NUMBER ADDRESS
// So we print out an error message and shutdown (don't worry about the
// 1 or 0 in the exit, that just lets the OS know why we shutdown)
else
{fprintf(stderr, "can't get \"%s\" host entry\n",hostname);
exit(1);
}
// Natural Completion of the application
exit(0);
}
2. Number to Dotted Decimal Format
Firstly 1 byte is 8 bits, this is what a "char" data type stores. But it stores
negative numbers too (-127 to 127) which is no good to us, so we make it "unsigned"
to allow us to store between (0 and 255) (2 to the power of 8 is 256). So to represent
a 32bit (4 byte) number it will be split into 4x unsigned char. Put exactly: "unsigned char var[4];".
Arrays are stored together in memory, so this array data type takes up the same space as
a "long" data type and in the same order. So this is why we can use "bcopy" to copy directly
from one to the other as if they were the same. Once copied we can access each array element
seperately allowing us to get each number
// These two lines are from localhost.c
hostiph = ntohl(hostip);
printf ("host IP address is %x\n",hostiph );
// I used the original structure here, but you should be able to use hostip (i think it may need to
// be passed by reference). "ddf" was declared as "unsigned char ddf[4];".
bcopy(phe->h_addr, ddf, 4);
// Print
printf ("host IP address (Dotted Decimal Format) is %d.%d.%d.%d\n", ddf[0], ddf[1], ddf[2], ddf[3]);
4. UDPechoc.c
Firstly we are given the declared variables in the "UDPecho" function. You can find
them commented below:
// Here we see there are two buffers, one for recieving stuff in and one
// for sending stuff out, they are both 120 characters long.
char buff[120] ="test string",buffin[120];
// This isn't used, probably the return status of a function
int s;
// The number of the socket we will use
int sockno;
// A pointer to a Socket Address Structure
struct sockaddr_in *addrptr;
// The length of the address maybe?
int alen;
// I didn't use these
int len1, len2;
Now what commands do we need?
// First of all open a socket, you should know this
if ((sockno = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("ERROR: Could not create local udp socket.\n");
exit(1);
}
// Get the ADDRESS STRUCTURE (pointer to) which represents the ADDRESS and PORT together
addrptr = getserveraddr(host, service);
// Get the size of this STRUCTURE
alen = sizeof(*addrptr);
// Send the Output buffer to "sockno", note it's address is casted to a pointer. The size
// is then sent, a 0, then the ADDRESS STRUCTURE is casted to a different type of ADDRESS
// STRUCTURE (remember it's a pointer that's sent), and lastly the length of the structure.
sendto(sockno, (char *)&buff, sizeof(buff), 0, (struct sockaddr *)addrptr, alen);
// Get from "sockno" and put into Input Buffer. Send the buffer (as is, it's a string, which
// is an array, so it's passed by reference), the size of the buffer, the ADDRESS STRUCTURE is
// sent again (cast) but since it's a pointer it will be changed and the ADDRESS of where this
// came from will come back to us. The alen variable is sent by reference so the size of this
// address will be returned
recvfrom(sockno, buffin, sizeof(buffin), 0, (struct sockaddr *)addrptr, &alen);