Fall Semester 2002


Lecture Notes Eight: Java Fundamentals

This serves as a quick introduction to Java.

For more introductory information about programming in Java please check A201 lecture notes.

We therefore start by testing our basic tools.

frilled.cs.indiana.edu%emacs HelloWorld.java
frilled.cs.indiana.edu%ls -ld HelloWorld.java
-rw-------   1 dgerman       122 Jan  6 19:18 HelloWorld.java
frilled.cs.indiana.edu%cat HelloWorld.java
class HelloWorld {
    public static void main(String[] args) {
	System.out.println("To infinity, and beyond!"); 
    }
}
frilled.cs.indiana.edu%javac HelloWorld.java
frilled.cs.indiana.edu%ls -l *
-rw-------   1 dgerman       438 Jan  6 19:23 HelloWorld.class
-rw-------   1 dgerman       122 Jan  6 19:18 HelloWorld.java
frilled.cs.indiana.edu%java HelloWorld
To infinity, and beyond!
frilled.cs.indiana.edu%
All of our programs will be presented in this way.

Ocasionally, we will have

EXERCISES

Now let's review the basics of Java.

The next program demonstrates

It also includes comments.
frilled.cs.indiana.edu%cat Fibonacci.java
class Fibonacci {
    public static void main(String[] args) {
	int low = 1, high = 1; 
	System.out.println(low); 
	while (high < 50) {
	    System.out.println(high); 
	    high = low + high; // new high 
	    low = high - low;  /* new low is (sum - old low)
				  that is, the old high */ 
	}
    }
}

frilled.cs.indiana.edu%javac Fibonacci.java
frilled.cs.indiana.edu%java Fibonacci
1
1
2
3
5
8
13
21
34
frilled.cs.indiana.edu%
The program declares and uses local variables.

Variables have types.

In Java we have the following types:

  1. primitive types
  2. reference types
There are eight primitive types:
  1. boolean

  2. char

  3. byte
  4. short
  5. int
  6. long

  7. float
  8. double
If a variable is not of primitive type (one of the above) it is of reference type.

Local variables need to be initialized by the programmer.

Let us remind ourselves that a method is composed of:

  1. a header (signature plus modifiers,) and
  2. a body
Note that the println method is overloaded as it accepts arguments of different types.

EXERCISES

Constants are values like: A named constant is a constant value referred to by a name.

Take a look at the following changes:

frilled.cs.indiana.edu%cat Fibonacci2.java
class Fibonacci2 {
    static final int MAX = 50; 
    /** Print the Fibonacci sequence for values < MAX */ 
    public static void main(String[] args) {
	int low = 1;
        int high = 1; 
	System.out.println(low); 
	while (high < MAX) {
	    System.out.println(high); 
	    high = low + high; // new high 
	    low = high - low;  /* new low is (sum - old low)
				  that is, the old high */ 
	}
    }
}

frilled.cs.indiana.edu%
You can group related constants within a class.

frilled.cs.indiana.edu%ls -l
total 4
-rw-------   1 dgerman       303 Jan  6 19:41 Fibonacci.java
-rw-------   1 dgerman       407 Jan  6 20:18 Fibonacci2.java
-rw-------   1 dgerman       122 Jan  6 19:18 HelloWorld.java
-rw-------   1 dgerman       163 Jan  6 20:22 Suit.java
frilled.cs.indiana.edu%cat Suit.java
class Suit {
    final static int CLUBS    = 1 ; 
    final static int DIAMONDS = 2 ; 
    final static int HEARTS   = 3 ; 
    final static int SPADES   = 4 ; 
}
frilled.cs.indiana.edu%javac Suit.java
frilled.cs.indiana.edu%ls -ld *.class
-rw-------   1 dgerman       308 Jan  6 20:22 Suit.class
frilled.cs.indiana.edu%
Note that you can compile, but not run, the Suit class.

EXERCISES

The while loop could be replaced by an equivalent for loop, as follows:
frilled.cs.indiana.eduls -l
total 5
-rw-------   1 dgerman       303 Jan  6 19:41 Fibonacci.java
-rw-------   1 dgerman       407 Jan  6 20:18 Fibonacci2.java
-rw-------   1 dgerman       122 Jan  6 19:18 HelloWorld.java
-rw-------   1 dgerman       491 Jan  6 21:15 ImprovedFibonacci.java
-rw-------   1 dgerman       163 Jan  6 20:22 Suit.java
frilled.cs.indiana.educat ImprovedFibonacci.java
class ImprovedFibonacci {
    /** Print out the first few Fibonacci 
     * numbers, marking evens with a '*' */
    static final int MAX_INDEX = 9; 
    
    public static void main(String[] args) {
	int low = 1;
        int high = 1; 
	String mark; 
	
	System.out.println("1: " + low);
	for (int i = 2; i < MAX_INDEX; i++) {
	    if (high % 2 == 0) mark = " *"; 
	    else mark = ""; 
	    System.out.println(i + ": " + high + mark); 
	    high += low; 
	    low = high - low;
	}
    }
}

frilled.cs.indiana.edujavac ImprovedFibonacci.java
frilled.cs.indiana.eduls -ld *.class
-rw-------   1 dgerman       819 Jan  6 21:17 ImprovedFibonacci.class
frilled.cs.indiana.edujava ImprovedFibonacci
1: 1
2: 1
3: 2 *
4: 3
5: 5
6: 8 *
7: 13
8: 21
frilled.cs.indiana.edu
As a side note, there is a closed formula for the Fibonacci numbers:
frilled.cs.indiana.edu%cat One.java
class One {
    public static void main(String[] args) {

	double a = (1 + Math.sqrt(5)) / 2; 

	double b = (1 - Math.sqrt(5)) / 2; 

	for (int i = 1; i < 9; i++) { 

	    System.out.print(i + ": "); 

	    System.out.println
		(Math.round
		 ((Math.pow(a, i) - Math.pow(b,i)) / Math.sqrt(5))); 

	}
    }
} 
frilled.cs.indiana.edu%java One
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
frilled.cs.indiana.edu%
EXERCISES In Java, each class has three kinds of members:

Here's the declaration of a simple class, and an example of its use:
class Point {
    public double x, y;
}

class Two {
    public static void main(String[] args) {
	Point lowerLeft = new Point(); 
	Point upperRight = new Point(); 
	Point middlePoint = new Point(); 

	lowerLeft.x = 0.0; 
	lowerLeft.y = 0.0; 
	
	upperRight.x = 1280.0; 
	upperRight.y = 1024.0; 
	
	middlePoint.x = 640.0; 
	middlePoint.y = 512.0; 	
    }
}
Here's a neat example of a class (static) variable:
class Point {
    public double x, y;
    public static Point origin = new Point(); 
}
Let's add some methods to this class now.

class Point {

    public double x, y;

    public static Point origin = new Point(); 

    public void clear() {
	x = 0; 
	y = 0; 
    }

    public double distanceTo(Point that) {
	double xdiff = x - that.x; 
	double ydiff = y - that.y; 
	return Math.sqrt(xdiff * xdiff + ydiff * ydiff); 
    }

    public void moveBy(double dx, double dy) {
	x += dx; 
	y += dy; 
    }

    public void moveTo(double x, double y) {
	this.x = x; 
	this.y = y; 
    }

    public String toString() {
	return "(" + this.x + ", " + this.y + ")";
    }

    Point (double a, double b) {
	this.x = a; 
	this.y = b; 
    }

    Point() {

    }

    public static void main(String[] args) {
	
	Point a = new Point(1, 0); 
	System.out.println("Point a has been created: " + a.toString()); 
	
	Point b = new Point(6, 6); 
	System.out.println("Point b has been created: " + b); 
	
	System.out.println
	    ("Distance from " + a + " to " + b + " is " + a.distanceTo(b)); 
	
	System.out.println
	    ("Distance from " + b + " to " + a + " is " + b.distanceTo(a)); 
	
	a.moveTo(0, 4); 
	System.out.println("Here's a after being moved to (0, 4): " + a); 
	
	b.moveBy(-2, 1); 
	System.out.println("Here's b after being moved by (-2, 1): " + b); 
	
	System.out.println
	    ("The distance between " + a + " and " + b + " is " + 
	     "now " + a.distanceTo(b) + " == " + b.distanceTo(a));
	
	System.out.println
	    ("The distance from " + a + " to origin " + Point.origin + 
	     " is " + a.distanceTo(Point.origin) + " (easy to check)."); 
	
	System.out.println
	    ("The distance from " + b + " to origin " + Point.origin + 
	     " is " + b.distanceTo(Point.origin) + "."); 
	
    }
}
Let's see this program running:

frilled.cs.indiana.edu%java Point
Point a has been created: (1.0, 0.0)
Point b has been created: (6.0, 6.0)
Distance from (1.0, 0.0) to (6.0, 6.0) is 7.810249675906654
Distance from (6.0, 6.0) to (1.0, 0.0) is 7.810249675906654
Here's a after being moved to (0, 4): (0.0, 4.0)
Here's b after being moved by (-2, 1): (4.0, 7.0)
The distance between (0.0, 4.0) and (4.0, 7.0) is now 5.0 == 5.0
The distance from (0.0, 4.0) to origin (0.0, 0.0) is 4.0 (easy to check).
The distance from (4.0, 7.0) to origin (0.0, 0.0) is 8.06225774829855.
frilled.cs.indiana.edu%
We've thus seen: EXERCISES Let's create a Calculator class.

frilled.cs.indiana.edu%cat Calculator.java
class Calculator {
    int add(int n, int m) {
	if (m == 0) return n;
	else return add(n+1, m-1);
    }
    public static void main(String[] args) {
	Calculator a = new Calculator(); 
	System.out.println(" 1 +  2  = " + a.add( 1, 2)); 
	System.out.println(" 4 +  1  = " + a.add( 4, 1)); 
	System.out.println("-1 +  2  = " + a.add(-1, 2)); 
    }
}

frilled.cs.indiana.edu%javac Calculator.java
frilled.cs.indiana.edu%java Calculator
 1 +  2  = 3
 4 +  1  = 5
-1 +  2  = 1
frilled.cs.indiana.edu%
EXERCISES Let's play a game.

frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      48 51 52 15 19  = 185
Here's the computer's: 29 31 41 44 40  = 185
This game is tied: 185 - 185
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      5 19 52 52 40  = 168
Here's the computer's: 39 19 39 1 44  = 142
You win this time by 26 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      6 34 19 37 28  = 124
Here's the computer's: 48 9 8 16 33  = 114
You win this time by 10 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      30 39 52 11 23  = 155
Here's the computer's: 19 39 21 8 50  = 137
You win this time by 18 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      27 44 38 48 39  = 196
Here's the computer's: 42 47 38 3 4  = 134
You win this time by 62 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      30 44 35 4 28  = 141
Here's the computer's: 43 2 52 18 26  = 141
This game is tied: 141 - 141
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      42 32 52 2 27  = 155
Here's the computer's: 20 35 37 47 19  = 158
Computer wins this time by 3 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      47 5 47 52 48  = 199
Here's the computer's: 45 50 42 36 38  = 211
Computer wins this time by 12 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      4 39 25 46 37  = 151
Here's the computer's: 47 10 42 38 19  = 156
Computer wins this time by 5 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      20 51 29 35 1  = 136
Here's the computer's: 46 49 23 52 21  = 191
Computer wins this time by 55 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      19 8 27 48 20  = 122
Here's the computer's: 16 33 18 46 45  = 158
Computer wins this time by 36 point(s).
frilled.cs.indiana.edu%java Game
Welcome to the Game.
Here's your hand:      24 11 8 44 48  = 135
Here's the computer's: 13 22 46 26 19  = 126
You win this time by 9 point(s).
frilled.cs.indiana.edu%
Here's an implementation of this game.

class Game {
    public static void main(String[] args) {
	System.out.println("Welcome to the Game."); 

	Hand yours     = new Hand(); 
	System.out.print("Here's your hand:      "); 

	yours.show(); 

	Hand computer  = new Hand(); 

	System.out.print("Here's the computer's: "); 

	computer.show(); 

	if (yours.value() > computer.value()) {

	    System.out.println("You win this time by " + 
			       (yours.value() - computer.value()) + 
			       " point(s)");

	} else if (yours.value() < computer.value()) {

	    System.out.println("Computer wins this time by " + 
			       (computer.value() - yours.value()) + 
			       " point(s).");

	} else {

	    System.out.println("This game is tied: " + 
			       yours.value() + " - " + 
			       computer.value()); 

	}

    }
}

class Hand {

    public static final int HAND_SIZE = 5; 

    int[] cards; 

    Hand() {
	cards = new int[HAND_SIZE]; 
        for (int i = 0; i < cards.length; i++) {
	    cards[i] = (int)(Math.random() * 52) + 1; 
	}
    }

    void show() {
	for (int i = 0; i < cards.length; i++) {
	    System.out.print(cards[i] + " "); 
	}
	System.out.println(" = " + this.value()); 
    }

    int value() { 
	int val = 0; 
	for (int i = 0; i < cards.length; i++) {
	    val += cards[i]; 
	}
	return val; 
    }

}
Here's a simpler example involving arrays:

frilled.cs.indiana.edu%cat Sum.java
class Sum {
    public static void main(String[] args) {
	int sum = 0; 
	for (int i = 0; i < args.length; i++) {
	    sum += Integer.parseInt(args[i]); 
	}
	System.out.println(sum); 
    }
}
frilled.cs.indiana.edu%javac Sum.java
frilled.cs.indiana.edu%java Sum
0
frilled.cs.indiana.edu%java Sum -1 2 3 -3
1
frilled.cs.indiana.edu%java Sum 1 2 3 4
10
frilled.cs.indiana.edu%
An array with length zero is an empty array.

The empty array is more than no array at all, as shown below:

frilled.cs.indiana.edu%cat Four.java
class Four {
    public static void main(String[] args) {
	int[] a = { 1, 2, 3, 4}; 
        int[] b = { };
	int[] c = new int[0]; 
	/* int[] d; */ 
	int[] e = null; 

	Four.show("a: ", a); 
	Four.show("b: ", b); 
	Four.show("c: ", c); 
	// Four.show("d: ", d); 
	Four.show("e: ", e); 
    }

    static void show(String u, int[] v) {

	if (v == null || v.length == 0) { // order is important 

	    System.out.println(u + "Not much to show."); 

	} else {

	    System.out.print(u); 
	    
	    for (int i = 0; i < v.length; i++) {
		System.out.print(v[i] + " "); 
	    }

	    System.out.println();

	} 

    }

}
frilled.cs.indiana.edu%javac Four.java
frilled.cs.indiana.edu%java Four
a: 1 2 3 4 
b: Not much to show.
c: Not much to show.
e: Not much to show.
frilled.cs.indiana.edu%
Exceptions could be thrown (and caught) when something bad happens.

frilled.cs.indiana.edu%cat Add.java
class Add {
    public static void main(String[] args) {

	int sum = 0; 

	try {

	    sum = 
		Integer.parseInt(args[0]) + 
		Integer.parseInt(args[1]); 

	    System.out.println("The sum is: " + sum); 

	} catch (Exception e) {

	    System.out.println("Exception caught (by us): " + e); 

	    System.out.println("Can't calculate sum, arguments missing."); 

	} finally {

	    System.out.println("Thanks for using this program."); 

	}
    }
}
frilled.cs.indiana.edu%javac Add.java
frilled.cs.indiana.edu%java Add 1 2
The sum is: 3
Thanks for using this program.
frilled.cs.indiana.edu%java Add 2 1
The sum is: 3
Thanks for using this program.
frilled.cs.indiana.edu%java Add -1 -2
The sum is: -3
Thanks for using this program.
frilled.cs.indiana.edu%java Add -1 7 2 3
The sum is: 6
Thanks for using this program.
frilled.cs.indiana.edu%java Add 1
Exception caught (by us): java.lang.ArrayIndexOutOfBoundsException
Can't calculate sum, arguments missing.
Thanks for using this program.
frilled.cs.indiana.edu%java Add
Exception caught (by us): java.lang.ArrayIndexOutOfBoundsException
Can't calculate sum, arguments missing.
Thanks for using this program.
frilled.cs.indiana.edu%
Strings are almost arrays of chars, but not quite.

frilled.cs.indiana.edu%cat Five.java
class Five {
    public static void main(String[] args) {

	String in = args[0]; 

	char[] a = new char[in.length()]; 

	for (int i = 0; i < args[0].length(); i++) {
	    a[i] = in.charAt(i); 
	}

	for (int i = 0; i < a.length; i++) {
	    System.out.print("(" + a[i] + ")"); 
	}

	System.out.println(); 

    }
}
frilled.cs.indiana.edu%javac Five.java
frilled.cs.indiana.edu%java Five
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at Five.main(Five.java:4)
frilled.cs.indiana.edu%java Five java
(j)(a)(v)(a)
frilled.cs.indiana.edu%java Five "I see..."
(I)( )(s)(e)(e)(.)(.)(.)
frilled.cs.indiana.edu%java Five wonderful
(w)(o)(n)(d)(e)(r)(f)(u)(l)
frilled.cs.indiana.edu%
EXERCISES First, here's a sample run with your program:
frilled.cs.indiana.edu%java Fifteen 0920 1025 
1 hour(s) 5 minutes
frilled.cs.indiana.edu%java Fifteen 1025 0920 
22 hour(s) 55 minutes
frilled.cs.indiana.edu%
Second, here's a starting point.

frilled.cs.indiana.edu%cat Fifteen.java
class Fifteen {
    public static void main(String[] args) {
	String 
	    one = args[0], 
	    two = args[1]; 

	String 
	    h1 = one.substring(0, 2), 
	    m1 = one.substring(2, 4), 
	    h2 = two.substring(0, 2), 
	    m2 = two.substring(2); 

	System.out.println("First time: " + h1 + 
			   " hours, and " + m1 + " minutes.");

	System.out.println("Second time: " + h2 + 
			   " hours, and "  + m2 + " minutes.");


    }
}
frilled.cs.indiana.edu%javac Fifteen.java
frilled.cs.indiana.edu%java Fifteen
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at Fifteen.main(Fifteen.java:4)
frilled.cs.indiana.edu%java Fifteen 0920 1000
First time: 09 hours, and 20 minutes.
Second time: 10 hours, and 00 minutes.
frilled.cs.indiana.edu%java Fifteen 1000 0945
First time: 10 hours, and 00 minutes.
Second time: 09 hours, and 45 minutes.
frilled.cs.indiana.edu%
Here's a simple example of inheritance or class extension.

frilled.cs.indiana.edu%cat Stages.java
class One {
    int add(int n, int m) {
	if (m == 0) return n;
	else return add(n+1, m-1);
    }
}

class Two extends One {
    int mul(int n, int m) {
	if (m == 1) return n; 
	else return add(n, mul(n, m-1)); 
    }
}

class Three extends Two {
    int pow(int n, int m) {
	if (m == 0) return 1; 
	else return mul(n, pow(n, m-1)); 
    }
}

class Calculator {
    public static void main(String[] args) {
	Three calc = new Three(); 
	int n = 3, m = 5; 
	System.out.println(n + " + " + m + " = " + calc.add(n, m)); 
	System.out.println(n + " * " + m + " = " + calc.mul(n, m)); 
	System.out.println(n + " ^ " + m + " = " + calc.pow(n, m)); 
    }
}

frilled.cs.indiana.edu%javac Stages.java
frilled.cs.indiana.edu%java Calculator
3 + 5 = 8
3 * 5 = 15
3 ^ 5 = 243
frilled.cs.indiana.edu%
Here's a different, somewhat similar, example on interfaces.

frilled.cs.indiana.edu%cat Example.java
interface Multiplier {
    int mul(int n, int m);
}

class Alpha implements Multiplier {
    public int mul(int n, int m) {
	return n * m; 
    }
}

class Beta implements Multiplier {
    public int mul(int n, int m) {
	int result = 0; 
	for (int i = 0; i < m; i++) 
	    result += n; 
	return result; 
    }
}

class Gamma implements Multiplier {
    public int mul(int n, int m) {
	if (m == 1) return n; 
	else return n + mul(n, m-1); 
    }
}

class Example {
    public static void main(String[] args) {
	Alpha a = new Alpha(); 
	Beta b = new Beta(); 
	Gamma g = new Gamma(); 
	int n = 5, m = 3; 
	System.out.println(n + " * " + m + " = " + a.mul(n,m) + " (by Alpha)");
	System.out.println(n + " * " + m + " = " + b.mul(n,m) + " (by Beta )");
	System.out.println(n + " * " + m + " = " + g.mul(n,m) + " (by Gamma)");
    }
}


frilled.cs.indiana.edu%javac Example.java
frilled.cs.indiana.edu%java Example
5 * 3 = 15 (by Alpha)
5 * 3 = 15 (by Beta )
5 * 3 = 15 (by Gamma)
frilled.cs.indiana.edu%
EXERCISES
class Weird {
    public static void main(String[] args) {
	String one = "Go Hoosiers!"; 
	Object two = "All the way!"; 
	System.out.println(one + " " + two); 
	two = one; 
	System.out.println(one + " " + two); 
        two = "All the way!"; 
	System.out.println(one + " " + two); 
	one = (String)two; 
	System.out.println(one + " " + two); 
	one = "Go Hoosiers!"; 
	System.out.println(one + " " + two); 
    }
}
The fundamental compilation unit in Java is the package.

frilled.cs.indiana.edu%cat One.java
import java.util.Date; 

class One {
    public static void main(String[] args) {
	System.out.println(new Date()); 
    }
}
frilled.cs.indiana.edu%cat Two.java
class Two {
    public static void main(String[] args) {
	System.out.println(new java.util.Date()); 
    }
}
frilled.cs.indiana.edu%cat Three.java
import java.util.*; 

class Three {
    public static void main(String[] args) {
	System.out.println(new Date()); 
    }
}
frilled.cs.indiana.edu%javac One.java Two.java Three.java
frilled.cs.indiana.edu%java One; java Two; java Three
Mon Mar 25 16:06:25 EST 2002
Mon Mar 25 16:06:26 EST 2002
Mon Mar 25 16:06:26 EST 2002
frilled.cs.indiana.edu%
EXERCISES
class Math {
    public static void main(String[] args) {
	System.out.println(Math.max(1, 2)); 
    }
}
This is the minimal that we need.

But, as the lab notes of this week are showing, we need a bit more.

So here's Part Two of these notes (more realistic in indicating how much Java is really required).

We discuss

and look at what it takes to develop

First, we are going to write a network client.

/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.com/javaexamples2.
 */
import java.io.*;
import java.net.*;

/**
 * This program connects to a server at a specified host and port.
 * It reads text from the console and sends it to the server.
 * It reads text from the server and sends it to the console.
 **/
public class GenericClient {
    public static void main(String[] args) throws IOException {
        try {
            // Check the number of arguments
            if (args.length != 2) 
                throw new IllegalArgumentException("Wrong number of args");
	    
            // Parse the host and port specifications
            String host = args[0];
            int port = Integer.parseInt(args[1]);
            
            // Connect to the specified host and port
            Socket s = new Socket(host, port);
	    
            // Set up streams for reading from and writing to the server.
            // The from_server stream is final for use in the inner class below
            final Reader from_server=new InputStreamReader(s.getInputStream());
            PrintWriter to_server = new PrintWriter(s.getOutputStream());
            
            // Set up streams for reading from and writing to the console
            // The to_user stream is final for use in the anonymous class below
            BufferedReader from_user = 
                new BufferedReader(new InputStreamReader(System.in));
	    // Pass true for auto-flush on println()
	    final PrintWriter to_user = new PrintWriter(System.out, true);
            
            // Tell the user that we've connected
            to_user.println("Connected to " + s.getInetAddress() +
			    ":" + s.getPort());
            
            // Create a thread that gets output from the server and displays 
            // it to the user.  We use a separate thread for this so that we
            // can receive asynchronous output
            Thread t = new Thread() {
		    public void run() {
			char[] buffer = new char[1024];
			int chars_read;
			try { 
			    // Read characters until the stream closes
			    while((chars_read = from_server.read(buffer)) != -1) {
				// Loop through the array of characters, and 
				// print them out, converting all \n characters
				// to the local platform's line terminator.
				// This could be more efficient, but it is probably
				// faster than the network is, which is good enough
				for(int i = 0; i < chars_read; i++) {
				    if (buffer[i] == '\n') to_user.println();
				    else to_user.print(buffer[i]);
				}
				to_user.flush();
			    }
			}
			catch (IOException e) { to_user.println(e); }
			
			// When the server closes the connection, the loop above
			// will end.  Tell the user what happened, and call
			// System.exit(), causing the main thread to exit along
			// with this one.
			to_user.println("Connection closed by server.");
			System.exit(0);
		    }
		};
            
            // We set the priority of the server-to-user thread above to be
            // one level higher than the main thread.  We shouldn't have to do
            // this, but on some operating systems, output sent to the console
            // doesn't appear when a thread at the same priority level is
            // blocked waiting for input from the console.
            t.setPriority(Thread.currentThread().getPriority() + 1);
            
            // Now start the server-to-user thread
            t.start();
            
            // In parallel, read the user's input and pass it on to the server.
            String line;
            while((line = from_user.readLine()) != null) {
                to_server.print(line + "\n");
                to_server.flush();
            }
            
            // If the user types a Ctrl-D (Unix) or Ctrl-Z (Windows) to end
            // their input, we'll get an EOF, and the loop above will exit.
            // When this happens, we stop the server-to-user thread and close
            // the socket.
	    
            s.close();
            to_user.println("Connection closed by client.");
	    System.exit(0);
        }
        // If anything goes wrong, print an error message
        catch (Exception e) { 
            System.err.println(e);
            System.err.println("Usage: java GenericClient <hostname> <port>");
        }
    }
}
Let's see how it works:
burrowww.cs.indiana.edu% pwd
/nfs/paca/home/user1/dgerman/browser/server
burrowww.cs.indiana.edu% ls -ld *
-rw-r--r--   1 dgerman  faculty      4749 Aug  6 23:43 GenericClient.java
burrowww.cs.indiana.edu% javac GenericClient.java
burrowww.cs.indiana.edu% java GenericClient burrowww.cs.indiana.edu 10200
Connected to burrowww.cs.indiana.edu/129.79.245.98:10200
GET /index.html 
<html>
  <head><title>Homework One Page</title></head>
  <body bgcolor=white>

  <center>
    <img src="http://www.cs.indiana.edu/images/academics.jpg">
  </center> <p> 

  SAMPLE HOMEWORK ONE PAGE: 
  Your first homework assignment is asking you to 

<ul> 

<li> install Apache, 
  and to 
<li> post a picture of yourself on the website, 

</ul> as I include above. 
  Please also provide links to a couple of other documents that
  describe your interests, and add more information to your page. 
  (For example my current interests are: 
<a href="http://www.cs.indiana.edu/classes/a201">A201</a> and 
<a href="http://www.cs.indiana.edu/classes/a348">A348</a>). 
Later you will provide links to your homework assignments from
this page. <p> 
  </body>
</html>
Connection closed by server.
burrowww.cs.indiana.edu% 
This is our (own) telnet. Now for the server part.

We start from this:

import java.io.*; 
import java.net.*; 

public class HTTPServer {
    public static void main(String[] args) throws Exception {
	final int httpd = Integer.parseInt(args[0]); // our port 
	ServerSocket ssock = new ServerSocket(httpd); 
	System.out.println("Have opened port " + httpd + " locally."); 
	Socket sock = ssock.accept(); 
	System.out.println("Client has made socket connection."); 
	OneConnection client = new OneConnection(sock); 
	String s = client.getRequest(); 
    }
}

class OneConnection {
    Socket sock; 
    BufferedReader in = null; 
    DataOutputStream out = null; 
    OneConnection(Socket sock) throws Exception {
	this.sock = sock;
	in = 
	    new BufferedReader
		(new InputStreamReader
		    (sock.getInputStream())); 
	out = new DataOutputStream(sock.getOutputStream()); 
    }
    String getRequest() throws Exception {
	String s = null; 
	while ((s = in.readLine()) != null) {
	    System.out.println("got: " + s); 
	}
	return s; 
    }
}
Let's see how we can use this.

We can start the server on tucotuco and connect from burrowww.

By the way:

burrowww.cs.indiana.edu% hostlist burrow 
burrowww
bandicoot
blesmol
bobac
degu
jerboa
marmot
molerat
prairiedog
suslik
tucotuco
whistlepig
woodchuck
burrowww.cs.indiana.edu% 
(Do you remember what that means?)

Here now is a simultaneous set of screens, first the server side:

tucotuco.cs.indiana.edu% javac HTT*.java
tucotuco.cs.indiana.edu% java HTTPServer 12345
Have opened port 12345 locally.
Client has made socket connection.
got: bye
got: I am here
got: klsjsajdasldkja
got: 
got: 
got: asdkjasjdaslkd
tucotuco.cs.indiana.edu% 
And the client side:
burrowww.cs.indiana.edu% java GenericClient tucotuco.cs.indiana.edu 12345
Connected to tucotuco.cs.indiana.edu/129.79.245.110:12345
bye
I am here
klsjsajdasldkja


asdkjasjdaslkd
^Cburrowww.cs.indiana.edu% 
So far, so good.

We, of course, can also make a connection using a web browser.

tucotuco.cs.indiana.edu% pwd
/nfs/paca/home/user1/dgerman/browser/server
tucotuco.cs.indiana.edu% java HTTPServer 12345
Have opened port 12345 locally.
Client has made socket connection.
got: GET / HTTP/1.0
got: Connection: Keep-Alive
got: User-Agent: Mozilla/4.79 [en] (X11; U; SunOS 5.8 sun4u)
got: Host: tucotuco.cs.indiana.edu:12345
got: Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
got: Accept-Encoding: gzip
got: Accept-Language: en
got: Accept-Charset: iso-8859-1,*,utf-8
got: 

Of, course, we don't show the browser.

But you can try, as well, and in the process see the HTTP headers.

Let's teach our server a little HTTP:

import java.io.*; 
import java.net.*; 

public class HTTPServer {
    public static void main(String[] args) throws Exception {
	final int httpd = Integer.parseInt(args[0]); // our port 
	ServerSocket ssock = new ServerSocket(httpd); 
	System.out.println("Have opened port " + httpd + " locally."); 
	Socket sock = ssock.accept(); 
	System.out.println("Client has made socket connection."); 
	OneConnection_A client = new OneConnection_A(sock); 
	String s = client.getRequest(); 
    }
}

class OneConnection {
    Socket sock; 
    BufferedReader in = null; 
    DataOutputStream out = null; 
    OneConnection(Socket sock) throws Exception {
	this.sock = sock;
	in = 
	    new BufferedReader
		(new InputStreamReader
		    (sock.getInputStream())); 
	out = new DataOutputStream(sock.getOutputStream()); 
    }
    String getRequest() throws Exception {
	String s = null; 
	while ((s = in.readLine()) != null) {
	    System.out.println("got: " + s); 
	}
	return s; 
    }
}

class OneConnection_A extends OneConnection {
    OneConnection_A (Socket sock) throws Exception {
	super(sock); 
    }
    String getRequest() throws Exception {
	String s = null; 
	while ((s = in.readLine()) != null) {
	    System.out.println("got: " + s); 
	    if (s.indexOf("GET") > -1) {
		out.writeBytes("HTTP-1.0 200 OK\r\n"); 
		s = s.substring(4); 
		int i = s.indexOf(" "); 
		System.out.println("file: " + s.substring(0, i)); 
		return s.substring(0, i); 
	    }
	}
	return null; 
    }
}
Here's what happens if you start it and call with
http://tucotuco.cs.indiana.edu:12345
from Netscape (or some other browser):
tucotuco.cs.indiana.edu% pwd
/nfs/paca/home/user1/dgerman/browser/server
tucotuco.cs.indiana.edu% ls -ld *
-rw-r--r--   1 dgerman  faculty      4749 Aug  6 23:43 GenericClient.java
-rw-r--r--   1 dgerman  faculty      1477 Aug  7 00:36 HTTPServer.java
tucotuco.cs.indiana.edu% javac *Server*.java
tucotuco.cs.indiana.edu% java HTTPServer 12345
Have opened port 12345 locally.
Client has made socket connection.
got: GET / HTTP/1.0
file: /
tucotuco.cs.indiana.edu%
Now we're getting so much closer:
import java.io.*; 
import java.net.*; 

public class HTTPServer {
    public static void main(String[] args) throws Exception {
	final int httpd = Integer.parseInt(args[0]); // our port 
	ServerSocket ssock = new ServerSocket(httpd); 
	System.out.println("Have opened port " + httpd + " locally."); 
	Socket sock = ssock.accept(); 
	System.out.println("Client has made socket connection."); 
	OneConnection_B client = new OneConnection_B(sock); 
	String s = client.getRequest(); 
        client.sendFile(s); 
    }
}

class OneConnection {
    Socket sock; 
    BufferedReader in = null; 
    DataOutputStream out = null; 
    OneConnection(Socket sock) throws Exception {
	this.sock = sock;
	in = 
	    new BufferedReader
		(new InputStreamReader
		    (sock.getInputStream())); 
	out = new DataOutputStream(sock.getOutputStream()); 
    }
    String getRequest() throws Exception {
	String s = null; 
	while ((s = in.readLine()) != null) {
	    System.out.println("got: " + s); 
	}
	return s; 
    }
}

class OneConnection_A extends OneConnection {
    OneConnection_A (Socket sock) throws Exception {
	super(sock); 
    }
    String getRequest() throws Exception {
	String s = null; 
	while ((s = in.readLine()) != null) {
	    System.out.println("got: " + s); 
	    if (s.indexOf("GET") > -1) {
		out.writeBytes("HTTP-1.0 200 OK\r\n"); 
		s = s.substring(4); 
		int i = s.indexOf(" "); 
		System.out.println("file: " + s.substring(0, i)); 
		return s.substring(0, i); 
	    }
	}
	return null; 
    }
}

class OneConnection_B extends OneConnection_A {
    OneConnection_B(Socket sock) throws Exception {
	super(sock); 
    }
    void sendFile(String fname) throws Exception {
	String where = "htdocs" + fname; 
	if (where.indexOf("..") > -1) 
	    throw new SecurityException("No access to parent dirs"); 
	System.out.println("Looking for " + where); 
        File f = new File(where); 
	DataInputStream din = new DataInputStream(new FileInputStream(f)); 
	int len = (int) f.length(); 
	byte[] buf = new byte[len]; 
	din.readFully(buf);
	out.writeBytes("Content-Length: " + len + "\r\n"); 
	out.writeBytes("Content-type: text/html\r\n\r\n"); 
	out.write(buf); 
	out.flush();
	out.close(); 
    }
}
Assume now you call
http://tucotuco.cs.indiana.edu:12345/one.html
using Netscape. Then the result is as follows.

First, the server reports all:

tucotuco.cs.indiana.edu% javac HTTPServer.java
tucotuco.cs.indiana.edu% du -a htdocs
1       htdocs/one.html
2       htdocs
tucotuco.cs.indiana.edu% cat htdocs/one.html
This is a very
simple file, 
               really... 
:-)

tucotuco.cs.indiana.edu% java HTTPServer 12345
Have opened port 12345 locally.
Client has made socket connection.
got: GET /one.html HTTP/1.0
file: /one.html
Looking for htdocs/one.html
tucotuco.cs.indiana.edu% 
Then, the file is shown in the browser.

(One can also verify that with our GenericClient).

Last improvement we need to make: turn the server in a multithreaded server.

import java.io.*; 
import java.net.*; 

public class HTTPServer {
    public static void main(String[] args) throws Exception {

	final int httpd = Integer.parseInt(args[0]); // our port 

	ServerSocket ssock = new ServerSocket(httpd); 

	while (true) {
	    Socket sock = ssock.accept(); 
	    System.out.println("** Client has made socket connection.");
	    OneConnection_C client = new OneConnection_C(sock); 
	    new Thread(client).start(); 
	}
    }
}

class OneConnection {
    Socket sock; 
    BufferedReader in = null; 
    DataOutputStream out = null; 
    OneConnection(Socket sock) throws Exception {
	this.sock = sock;
	in = 
	    new BufferedReader
		(new InputStreamReader
		    (sock.getInputStream())); 
	out = new DataOutputStream(sock.getOutputStream()); 
    }
    String getRequest() throws Exception {
	String s = null; 
	while ((s = in.readLine()) != null) {
	    System.out.println("got: " + s); 
	}
	return s; 
    }
}

class OneConnection_A extends OneConnection {
    OneConnection_A (Socket sock) throws Exception {
	super(sock); 
    }
    String getRequest() throws Exception {
	String s = null; 
	while ((s = in.readLine()) != null) {
	    System.out.println("got: " + s); 
	    if (s.indexOf("GET") > -1) {
		out.writeBytes("HTTP-1.0 200 OK\r\n"); 
		s = s.substring(4); 
		int i = s.indexOf(" "); 
		System.out.println("file: " + s.substring(0, i)); 
		return s.substring(0, i); 
	    }
	}
	return null; 
    }
}

class OneConnection_B extends OneConnection_A {
    OneConnection_B(Socket sock) throws Exception {
	super(sock); 
    }
    void sendFile(String fname) throws Exception {
	String where = "htdocs" + fname; 
	if (where.indexOf("..") > -1) 
	    throw new SecurityException("No access to parent dirs"); 
	System.out.println("Looking for " + where); 
        File f = new File(where); 
	DataInputStream din = new DataInputStream(new FileInputStream(f)); 
	int len = (int) f.length(); 
	byte[] buf = new byte[len]; 
	din.readFully(buf);
	out.writeBytes("Content-Length: " + len + "\r\n"); 
	out.writeBytes("Content-type: text/html\r\n\r\n"); 
	out.write(buf); 
	out.flush();
	out.close(); 
    }
}

class OneConnection_C extends OneConnection_B implements Runnable {
    OneConnection_C(Socket sock) throws Exception {
	super(sock); 
    }
    public void run() {
	try {
	    String filename = getRequest(); 
	    sendFile(filename); 
	} catch (Exception e) {
	    System.out.println("Exception: " + e); 
	}
    }
}
This way it can receive and service more than one call.

tucotuco.cs.indiana.edu% java HTTPServer 12345
** Client has made socket connection.
got: GET /one.html HTTP/1.0
file: /one.html
Looking for htdocs/one.html
** Client has made socket connection.
got: GET /two.html HTTP/1.0
file: /two.html
Looking for htdocs/two.html
Exception: java.io.FileNotFoundException: htdocs/two.html (No such file or directory)
** Client has made socket connection.
got: GET /one.html HTTP/1.0
file: /one.html
Looking for htdocs/one.html
^Ctucotuco.cs.indiana.edu%
The output above was generated by calling the server three times:
http://tucotuco.cs.indiana.edu:12345/one.html
http://tucotuco.cs.indiana.edu:12345/two.html
http://tucotuco.cs.indiana.edu:12345/one.html
One of the files is missing, hence the exception.

I have two more references for I/O and networking.

They're here:

And here's a very basic reference to


Last updated: Sep 22, 2002 by Adrian German for A348/A548