Understanding Network Programming to Date

I think the link we got in the mail is a little too much information, do remember there is an order to the learning process and we haven't got to the server yet so no need to complete confuse ourselves. Here is an explaination of the code we need to know so far and what it does, I will not spoon feed you because it would not help you.

1. Localhost.c
2. Number to Dotted Decimal Format
3. Server/Client
4. UDPechoc.c


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]);


3. Server/Client

There are two applications, udpechos.c (the server) which does not need any editting and udpechoc.c (the client) which does. Usage of these applications:
./udpechos <port> &

The above command will run the server in the background and you can use "ps" to find it's
process id later and shut it down with "kill <pid>".

./udpechoc localhost <port>

This will run the client, but the client is missing code which you need to put in
so it won't work first time.

The server listens for strings sent to it and then sends them back. "sendto" and "recvfrom" are the only forms of communication you have with the server. You can send "zz\n" to the server to shut it down. This is obvious if you read the server code.

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);