exercise-1.txt

Yu Cheng (Jade)
ICS 451
Exercise 1
January 21, 2009

[Telnet Exercise]

Use telnet to connect to the daytime port of a variety of hosts. The command (on
Unix/Linux) is "telnet hostname daytime". Connect to each of the following
hosts:

    * www.soest.hawaii.edu
    * mauicc.hawaii.edu
    * cs.berkeley.edu
    * nist1.symmetricom.com

Did you get the same time from each one? If not, explain the difference.

A: No, they are different.

--------------------------------------------------------------------------------
    * www.soest.hawaii.edu:   Wed Jan 14 21:52:57 2009
    * mauicc.hawaii.edu:      Wednesday, January 14, 2009 10:07:39PM-HST
    * cs.berkeley.edu:        Wed Jan 14 23:54:48 2009
    * nist1.symmetricom.com:  54846 09-01-15 07:55:19 00 0 0 414.3 UTC(NIST) *
--------------------------------------------------------------------------------

Because they are at differet time zone.

What happens if you attempt to connect to the daytime port of www2.hawaii.edu?

--------------------------------------------------------------------------------
Connecting To www2.hawaii.edu...Could not open connection to the host, on port d
aytime: Connect failed
--------------------------------------------------------------------------------

You can use telnet to connect to port 80 of a machine that is running a web
server.

--------------------------------------------------------------------------------
bash-2.03$ telnet www.hawaii.edu 80
Trying 128.171.224.100...
Connected to web00.its.hawaii.edu.
Escape character is '^]'.
GET / HTTP/1.1
Host: www.hawaii.edu
Accept: */*
--------------------------------------------------------------------------------

I received the page contents of www.hawaii.edu.


[Ping Exercise]

--------------------------------------------------------------------------------
I used this site to calculte the straight distance of places.
  http://www.daftlogic.com/projects-google-maps-distance-calculator.htm

  * www2.hawaii.edu:   1.5  km  => 0.005 ms * 2 = 0.01 ms
  64 bytes from pwb01-2.its.hawaii.edu (128.171.94.193): icmp_seq=1. time=0. ms

  * mauicc.hawaii.edu:      92   km  => 0.307 ms * 2 = 0.61 ms
  64 bytes from mauicc.hawaii.edu (166.122.60.134): icmp_seq=1. time=4. ms

  * cs.berkeley.edu:        3876 km  => 12.92 ms * 2 = 16 ms
  64 bytes from mx1.EECS.Berkeley.EDU (169.229.60.161): icmp_seq=1. time=70. ms

  * www.uchicago.edu:       4255 km  => 14.18 ms * 2 = 28 ms
  64 bytes from uchicago.edu (128.135.13.114): icmp_seq=3. time=103. ms

  * www.princeton.edu:      7944 km  => 26.48 ms * 2 = 53 ms
  64 bytes from Princeton.EDU (128.112.128.81): icmp_seq=2. time=133. ms

  * nist1.symmetricom.com:
  64 bytes from nist1.symmetricom.com (69.25.96.13): icmp_seq=4. time=59. ms
--------------------------------------------------------------------------------

I observed that the farther the phisical distance is the longer it takes.  But
the actual time is longer than the estimated time.  "Ping does not estimate the
round-trip time, as it does not factor in the user's connection speed, but
instead is used to record any packet loss, and print a statistical summary when
finished." -- Wikipedia


[Traceroute Exercise]

--------------------------------------------------------------------------------
  * www2.hawaii.edu:       2  hops

  * mauicc.hawaii.edu:     7  hops

  * cs.berkeley.edu:       14 hops

  * www.uchicago.edu:      12 hops

  * www.princeton.edu:     over 30 hops

  * nist1.symmetricom.com: over 30 hops
--------------------------------------------------------------------------------


[Unix client Exercise]

Question 1: Reading data

I added the following code in the client.c file to print out the response from
the server.  This function is called after sending the user input string and
before closing the socket.

--------------------------------------------------------------------------------
static void print_response(int s) {
	char ch;

	do {
		// Read a character from the socket and check for an error.
		if (1 != recv(s, &ch, 1, 0))
			break;

		// Print the character.
		printf("%c", ch);

		// Loop over one line of data.
	} while (ch != '\n');

	printf("\n");
}
--------------------------------------------------------------------------------

Question 2: Change host and port

I changed the portnumber to 13, which is the daytime port number.  I modified
the client code to take in two argument line inputs.  The first one is the host
address, and the second one is the number of connections to make.  The client
prints out the first and last server responses.  Attached below is the modified
client code.

--------------------------------------------------------------------------------
:
// The port number the server is listening on.
#define portnumber 13
:

int main(int argc, const char * argv[]) {
	int                  s; // socket descriptor
	struct protoent    * protocolentry;
	struct hostent     * hostentry;
	struct sockaddr_in   sin;
	struct sockaddr    * sap;
	int                  i;
	int                  times;

	if (argc != 3) {
		fprintf(stderr, "usage: client host iterations\n");
		return EXIT_FAILURE;
	}

	// Reinterpret the sockaddr_in as a sockaddr.
	sap = (struct sockaddr *)&sin;

	// Check if the TCP protocol is available.
	protocolentry = getprotobyname("tcp");
	if (protocolentry == NULL)
		error("getprotobyname");

	if (sscanf(argv[2], "%d", &times) != 1) {
		fprintf(stderr, "%s is invalid input.\n", argv[2]);
		return EXIT_FAILURE;
	}

	// Get the IP address for a specified name and check for errors.
	hostentry = gethostbyname(argv[1]);
	if (hostentry == NULL || hostentry->h_addr_list == NULL)
		error("gethostbyname");

	// Set all bytes in sockaddr_in to zero.
	memset(&sin, 0, sizeof(sin));

	// Set the address family, port number, and IP address.
	sin.sin_family = AF_INET;
	sin.sin_port   = htons(portnumber);
	memcpy(&sin.sin_addr, hostentry->h_addr_list[0], hostentry->h_length);

	for(i = 0; i < times; i++) {
		// Create the socket descriptor and check for an error.
		s = socket(AF_INET, SOCK_STREAM, protocolentry->p_proto);
		if (s < 0)
			error("socket");

		// Connect to the server and check for an error.
		if (connect(s, sap, sizeof(sin)) < 0)
			error("connect");

		if (i == 0 || i == times - 1)
			print_response(s);

		// Close the connection and check for an error.
		if (close(s) < 0)
			error("close");
	}
	return EXIT_SUCCESS;
}
--------------------------------------------------------------------------------

Question 3: Compute the time per connection

Then I used cs.berkeley.edu as the daytime server. (They might not like it...)
Then I tried to make 1000 connections.

--------------------------------------------------------------------------------
	bash-2.03$ ./client cs.berkeley.edu 1000
	Sun Jan 18 17:37:32 2009

	Sun Jan 18 17:38:42 2009
--------------------------------------------------------------------------------

I used a stopwatch to time this procedure for a couple times.  It took 1 min 11
secs.  So the average time for building and closing a connection is about 71 ms.


[Unix server Exercise]

I got "bind: Address already in use" message.  I need to kill the previous
process before starting a new one.

--------------------------------------------------------------------------------
	bash-2.03$ ./server &
	[1] 24792
	bash-2.03$ ./server &
	[2] 24795
	bash-2.03$ bind: Address already in use
--------------------------------------------------------------------------------

Question 1: Using Telnet to test your server

I changed the port number that the server listens on to 15000.  I telneted into
the server and entered a string "hello, world!".

--------------------------------------------------------------------------------
	$ telnet uhunix.its.hawaii.edu 15000
	(hello, world!)

	!dlrow ,olleh


	Connection to host lost.
--------------------------------------------------------------------------------

[Question Section]

1: Where does the program fail if the port is in use?
A: Program fails when it trying to bind.

--------------------------------------------------------------------------------
	:
	// Reserve the port and check for an error.
	if (bind(passive, sap, sizeof(sin)) != 0)
		error("bind");
	:			--------------------------------------------------------------------------------

2-1: What does the "fork" command do?

A: It starts another process (B) with the same running state as the process that
started it (A).  The fork function returns zero to process B, and it returns the
process id of B (a none-zero value) to process A.

2-1: Can you modify the program to remove "fork" and have a server that only
handles one connection at a time?

A: I modified the server code.  Basically, just commented out the fork function
call and the exit statement.  For my example, it sents back txt "text..." for
each connection.

--------------------------------------------------------------------------------
	while ((session = accept(passive, sap, &adrsize)) >= 0) {
		if (send(session, "test...", 7, 0) < 0)
			error("write");

		//Close the connection.
		if (close(session) < 0)
			error("child close");
	}
--------------------------------------------------------------------------------
	bash-2.03$ ./server &
	[1] 8091
	bash-2.03$ ./client localhost 4
	test...
	test...
	test...
	test...
--------------------------------------------------------------------------------

2-3: See what happens if you try to connect another client while the server is connected to the first client.

A: First I tested the server code with the fork operation.  I ran the server and
client (1).  Client 1 prompted the user input.  I put it in background and
started another client (2).  Client 2 prompted the user input.  I typed "jade".
I got "edaj" back.  Then I put Client 1 foreground and entered "hello".  I got
back "olleh".  So, both of client 1 and 2 were connected to the server at the
same time.

--------------------------------------------------------------------------------
bash-2.03$ ./server &                            ===> start the server
[1] 10680

bash-2.03$ ./client localhost 1                  ===> start client 1
enter a string:

^Z
[2]+  Stopped                 ./client localhost 1

bash-2.03$ bg
[2]+ ./client localhost 1 &
[2]+  Stopped                 ./client localhost 1

bash-2.03$ ./client localhost 1                  ===> start client 2
enter a string:  jade
edaj                                             ===> response from the server

bash-2.03$ jobs
[1]-  Running                 ./server &
[2]+  Stopped                 ./client localhost 1

bash-2.03$ fg
./client localhost 1
hello
olleh                                            ===> response from the server
--------------------------------------------------------------------------------

Then I tested the server code without the fork operation.  I ran the server and
client (1).  Client 1 prompted the user input.  I put it in background and
started another client (2).  Client 2 prompted the user input.  I typed "jade".
program waited forever.  So, the second client was waiting to connect to the
server.  Multiple clients can't connect at the same time.

--------------------------------------------------------------------------------
bash-2.03$ ./server &                            ===> start the server
[1] 10745

bash-2.03$ ./client localhost 1                  ===> start client 1
enter a string:

^Z
[2]+  Stopped                 ./client localhost 1

bash-2.03$ bg
[2]+ ./client localhost 1 &
[2]+  Stopped                 ./client localhost 1

bash-2.03$ ./client localhost 1                  ===> start client 2
enter a string:  jade
                                                 ===> waits forever...
--------------------------------------------------------------------------------

3-1: C has two ways of representing strings: null-terminated and length-based.
Which way is used by the "read" and "write" or "recv" and "send" system calls?

A: These system calls use lenth-based way to represent strings.

3-2: Which way is used by "strlen" and "strcpy"?

A: They use null-terminated way to represent strings.

3-3: Would it be a good idea to use "printf ("%s\n", buf);" with the result of
reading the data? Why or why not?

A: No, it's not, unless we purposefully put a '\0' at the end of the buffer
because printf("%s\n", buf) looks for the null-terminater as the end of the buf.
It might go into the following memory space and prints out more than we need.
Valid HTML 4.01 Valid CSS