Menu

Class 20: Networks I


Reading
APUE sections 16.3.1 - 16.3.3.

Homework
Printout the Homework and answer the questions on that paper.

The rest of the course
We've talked about programs that get input and/or output via Looked at another way, we've talked about communicating data for Now its time to extend to communication between multiple processes running on different machines. This means communicating over a network. Our focus is going to be on communicating over the internet, though you should realize there are other kinds of networks.

Internet Intro
Glossary (part 1)

The complexity "under the hood" of sending a simple message over the internet is amazing. There's a utility called traceroute that shows how a singe message (a packet) gets sent from one host to another. The following shows the route from here in the cs department to a web-server in Austria.

bash$ traceroute www.risc.uni-linz.ac.at
traceroute to www.risc.uni-linz.ac.at (193.170.37.138), 30 hops max, 40 byte packets
 1  core-rt1.cs.usna.edu (131.122.88.251)  0.727 ms  0.266 ms  0.251 ms
 2  internet-r1.usna.edu (192.190.228.1)  0.762 ms  0.613 ms  0.760 ms
 3  sdp.usna.dren.net (138.18.45.5)  0.873 ms  0.917 ms  0.775 ms
 4  ge-3-2-0.wae.dren.net (138.18.1.253)  4.452 ms  4.682 ms  4.507 ms
 5  POS4-1.GW2.DCA8.ALTER.NET (157.130.49.1)  5.734 ms  5.233 ms  4.687 ms
 6  0.so-3-0-0.XL1.DCA8.ALTER.NET (152.63.39.174)  5.051 ms  5.291 ms  15.561 ms
 7  0.so-1-1-2.XL3.IAD8.ALTER.NET (152.63.38.129)  7.074 ms  6.022 ms  5.833 ms
 8  0.xe-8-1-0.BR2.IAD8.ALTER.NET (152.63.37.149)  6.061 ms 0.xe-5-0-0.BR2.IAD8.ALTER.NET (152.63.41.229)  6.307 ms 0.xe-8-1-0.BR2.IAD8.ALTER.NET (152.63.37.149)  6.428 ms
 9  xe-5-1-0.edge1.washinton4.level3.net (4.68.62.97)  6.296 ms  6.134 ms te-11-0-0.edge1.Washington4.level3.net (4.68.111.253)  5.800 ms
10  vlan89.csw3.Washington1.Level3.net (4.68.17.190)  8.472 ms  7.399 ms vlan79.csw2.Washington1.Level3.net (4.68.17.126)  6.963 ms
11  ae-62-62.ebr2.Washington1.Level3.net (4.69.134.145)  8.522 ms  8.857 ms ae-82-82.ebr2.Washington1.Level3.net (4.69.134.153)  7.327 ms
12  ae-43-43.ebr2.Frankfurt1.Level3.net (4.69.137.57)  96.266 ms  96.350 ms  98.449 ms
13  ae-82-82.csw3.Frankfurt1.Level3.net (4.69.140.26)  103.416 ms ae-72-72.csw2.Frankfurt1.Level3.net (4.69.140.22)  111.154 ms ae-62-62.csw1.Frankfurt1.Level3.net (4.69.140.18)  104.436 ms
14  ae-81-81.ebr1.Frankfurt1.Level3.net (4.69.140.9)  99.289 ms ae-61-61.ebr1.Frankfurt1.Level3.net (4.69.140.1)  94.689 ms ae-81-81.ebr1.Frankfurt1.Level3.net (4.69.140.9)  99.981 ms
15  ae-6-6.car1.Vienna1.Level3.net (4.69.135.33)  108.151 ms  107.961 ms  109.768 ms
16  ae-11-11.car2.Vienna1.Level3.net (4.69.135.30)  107.327 ms  108.842 ms  107.801 ms
17  vlan301.wien21.aco.net (212.73.203.18)  109.829 ms  111.990 ms  110.421 ms
18  vlan312.linz2.aco.net (193.171.15.6)  113.926 ms  112.485 ms  112.274 ms
19  vlan313.linz1.aco.net (193.171.15.9)  112.152 ms  183.114 ms  111.801 ms
20  jku-gw.edvz.uni-linz.ac.at (193.171.22.26)  113.047 ms  111.567 ms  112.857 ms
21  jkuc3hb1.edvz.uni-linz.ac.at (140.78.200.225)  114.143 ms  123.798 ms  122.666 ms
22  Router.RISC.Uni-Linz.AC.AT (140.78.222.31)  121.514 ms  123.248 ms  125.288 ms
23  crow.risc.uni-linz.ac.at (193.170.37.138)  122.484 ms  119.743 ms  114.332 ms
	  
Notice that each host is described by a name and by four number "dotted" together.

Names, Names, Names
Before we can write programs that communicate over the internet, we need to deal with a very fundamental issue: How do you find a given host? After all, you'll have to specify who you want to communicate with (or "with whom" if you want to be grammatically correct!) When communicating over the phone, we distinguish between a person's name and their phone number. The latter is actually sufficient to communicate, even without the former. The name, however, is not sufficient to communicate. We require an external service (the phonebook) to retrieve the phone number from the name in order to actually communicate.

We'll see that it works the same way with networking using the IP protocol: a host has a name (called a fully qualified domain name) and an address (a number called its IP address). The IP address is what you really need in order to communicate with a host. The name is, in and of itself, not sufficient. We require an external service called DNS to retreive an IP address from a fully qualified domain name --- in other words, DNS acts like the phonebook.

IP addresses themselves are 32-bit (unsigned) numbers. However, people seem to find things like 2205833223 to be less than catchy. So we tend to use "dotted quad" notation instead, which looks like this: 131.122.88.7. The way you interpret this is 131.122.88.7 → 131*2563 + 122*2562 + 88*256 + 7 = 2205833223. So you do need to know how to convert between these representations.

Oh, and there's a hitch: different machines represent a 4-byte integer like 2205833223 differently. It's called byte order or "endianness". If A is an array of four bytes, in little-endian byteorder you'd have the integer A[0] + A[1]*256 + A[2]*2562 + A[3]*2563, while in big-endian byteorder you'd have the integer A[0]*2563 + A[1]*2562 + A[2]*256 + A[3]. In the normal course of events this distinction doesn't matter, because the machine consistently stores everything the same way. However, when communicating across a network that contains many different kinds of machines, we need to agree on which byte order we want. The IP protocol (remember, a protocol is an agreement about how to communicate) specifies "network byte order" as big-endian. So we have that to worry about too.

IP Addresses
There's a standard Unix library called the sockets library that contains functions for network operations. Two that are relevant to byte order are:
uint32_t htonl(uint32_t hostlong);  ← host byte order to network byte order (l = long = 32 bit)
uint32_t ntohl(uint32_t netlong);   ← network byte order to host byte order (l = long = 32 bit)
	
The type uint32_t is just unsigned int on our system. It means 32-bit unsigned int. Two more that are useful for us are:
in_addr_t inet_addr(const char *cp);
char *inet_ntoa(const struct in_addr in);
	
They allow us to convert IP addresses back and forth from a string containing the dotted quad as text to 32-bit IP addresses (in network byte order, of course). The type in_addr_t is, once again, just another name for unsigned int on our system. So what about argument struct in_addr in? The struct includes the following member:
in_addr_t s_addr;

Below is a program that converts IP addresses in dotted quad representation to IP addresses in their literal repersentation as a single number. To compile it you must include the -lnsl option, which links to a system library that is not in gcc's default path. For example:

gcc -o quad2int quad2in.c -lnsl

/*******************************************
 * quad2int <dottedquad>
 * Takes a dotted quad as a command-line
 * argument and prints out the integer
 * corresponding to the dotted quad.  We
 * convert that integer back to a dotted 
 * quad, just for run.
 *******************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
  if (argc != 2) { 
    printf("%s <dottedquad>\n",argv[0]); 
    exit(1); }

  /* Take string containing dotted quad
     and get the IP address in network
     byte order. */
  in_addr_t a = inet_addr(argv[1]);

  /* Convert to local host byte order
     and print as an integer. */
  printf("%u\n",ntohl(a));

  /* Convert the address (in network
     byte order) back to a dotted quad.
     Note: it should be the same as 
     argv[1]! */
  struct in_addr ia;
  ia.s_addr = a;
  printf("%s\n",inet_ntoa(ia));
  return 0;
}