You are encouraged to work in groups for this exercise.
To turn in this exercise, simply turn in the answers to section 1.1 (did you get the same time from each one? If not why not?), section 1.2 (a table of distances, computed Round-Trip Times, measured Round-Trip Times, and explanation for differences), section 2.4 (how long per connection?), and section 3.5. Do not send any code, but do send any questions you have.
What happens if you attempt to connect to the daytime port of www2.hawaii.edu?
You can use telnet to connect to port 80 of a machine that is running a web server. Then, type (or cut and paste):
GET path HTTP/1.1 Host: web.site.domain.name Accept: */*path can be as simple as a "/", or as complicated as you wish to type. Be sure to include the empty line. This should get you the HTML for the document specified by path, though some servers may give you unexpected responses.
For example, if connecting to port 80 of www.hawaii.edu,
GET / HTTP/1.1 Host: www.hawaii.edu Accept: */*
In HTTP 1.1, there may be one or more header fields following the initial line. Project 1 will explore this.
Can you justify the round-trip times to each of these hosts by considering just the speed of light? In other words:
/* client.c: program to connect to server. */
/* on sun/solaris/oracle, compile with: gcc -o client client.c -lsocket -lnsl */
/* on other systems, might compile with: gcc -o client client.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define portnumber 4872
#define BUFSIZE 1000
#define error(s) { perror(s); exit(1); }
main ()
{
int s;
struct protoent * protocolentry;
struct hostent * hostentry;
struct sockaddr_in sin;
struct sockaddr * sap = (struct sockaddr *) &sin;
char buf[BUFSIZE];
if ((protocolentry = getprotobyname("tcp")) == NULL) error("getprotobyname");
if ((s = socket(AF_INET, SOCK_STREAM, protocolentry->p_proto)) < 0)
error("socket");
hostentry = gethostbyname("www2.ics.hawaii.edu");
if ((hostentry == NULL) || (hostentry->h_addr_list == NULL))
error("gethostbyname");
memset (&sin, 0, sizeof (sin));
sin.sin_family = AF_INET;
memcpy(&(sin.sin_addr), hostentry->h_addr_list[0], hostentry->h_length);
sin.sin_port = htons(portnumber);
if (connect(s, sap, sizeof(sin)) < 0) error("connect");
printf ("enter a string: ");
fgets (buf, BUFSIZE, stdin);
if (send(s, buf, strlen(buf), 0) < 0) error("send");
if (close(s) < 0) error("close");
}
This program contacts a server running on the machine
"www2.ics.hawaii.edu" and gives it the string you entered.
If, for any reason, the server is not running, run your own server (part 3 of this exercise), and modify the domain name and port number to identify this server that you are running.
If you run your server on a machine, and are unable to connect to it from outside that machine, but have no problem connecting to it from the local host, that machine may be behind a firewall.
Make sure you understand what each line in this file does. If not, work with your group (if you have one), or post to the class mailing list (we might get a good discussion going!) or ask the instructor or study the textbook.
If you are on a machine that is not a sun, you may have to use different include files or different link switches (the "-l" switches). On Linux, you do not need any "-l" switches.
You are welcome (but not required) to rewrite this program to run on a Windows system.
Save a copy of this program for later use, in part (3.1).
/* server.c: program to accept input from clients. */
/* on sun/solaris/oracle, compile with: gcc -o server server.c -lsocket -lnsl */
/* on other systems, might compile with: gcc -o server server.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <netdb.h>
#define portnumber 4321
#define BUFSIZE 100
#define error(s) { perror(s); exit(1); }
main ()
{
int passive, session;
struct sockaddr_in sin;
struct sockaddr * sap = (struct sockaddr *) &sin;
ssize_t count;
int i = 0, pos = 0;
socklen_t adrsize;
char buf[BUFSIZE] = "";
struct sigaction siga;
struct protoent * protocolentry;
if ((protocolentry = getprotobyname("tcp")) == NULL) error("getprotobyname");
if ((passive = socket(PF_INET, SOCK_STREAM, protocolentry->p_proto)) < 0)
error("socket");
memset (&sin, 0, sizeof (sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(portnumber);
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(passive, sap, sizeof (sin)) != 0) error("bind");
/* make sure child processes are really detached (see exit(2)) */
if (sigaction (SIGCHLD, NULL, &siga) < 0) error ("sigaction/get");
siga.sa_flags |= SA_NOCLDWAIT | SA_NOCLDSTOP;
if (sigaction (SIGCHLD, &siga, NULL) < 0) error ("sigaction");
/* specify the maximum queue length */
if(listen(passive, 5) < 0) error("listen");
adrsize = sizeof (sin);
while ((session = accept(passive, sap, &adrsize)) >= 0) {
if (fork() == 0) { /* child process */
count = recv(session, buf, BUFSIZE - 1, 0);
buf[count] = '\0';
pos = count - 1;
if (buf[pos] == '\n') pos--;
for (i = 0; i <= pos; ) {
int swap = buf[i];
buf[i++] = buf[pos];
buf[pos--] = swap;
}
if (send(session, buf, count, 0) < 0) error("write");
if (close(session) < 0) error("child close");
exit(0);
} else { /* parent process */
if (close(session) < 0) error("parent close");
}
}
}
Again, make sure you understand what each line in this file does, but this time also check to see that the return values from each function are checked for errors. This is very important in network programming -- many errors are possible, depending on the state of the network and the remote (and local) machine.
If you have trouble running the server (because bind fails), someone else on the same machine may be using the same port number, so try using a different port number. Be sure the port number in the client matches the port number in the server.
Also use telnet (instead of the specialized client) to connect to your server, enter strings, and look at the result. This is how telnet is used to debug servers.