|
Fall Semester 2002 |
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
HelloWorld as above.
HelloWorld and see what errors
you get.
The next program demonstrates
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:
boolean
char
byte
short
int
long
float
double
Local variables need to be initialized by the programmer.
Let us remind ourselves that a method is composed of:
println method is overloaded
as it accepts arguments of different types. EXERCISES
12
17.9, and
"Strings like this."
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
HelloWorld application to use a named
string constant as the string to print.
PI
defined in class Math.
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
i counts backward
instead of forward (use closed formula)
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:
We've thus seen: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%
Point which sets the current object's
coordinates to those of a passed in Point object. Call this new
method moveTo, and use it in a few examples.
clone() method to the Point class,
that returns a copy of the Point it is invoked on.
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
int fibonacci(int n) to
all Calculators.
add method so it also works for
negative values int its second argument.
Here's an implementation of this 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%
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
Second, here's a starting point.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%
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
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:
(Do you remember what that means?)burrowww.cs.indiana.edu% hostlist burrow burrowww bandicoot blesmol bobac degu jerboa marmot molerat prairiedog suslik tucotuco whistlepig woodchuck burrowww.cs.indiana.edu%
Here now is a simultaneous set of screens, first the server side:
And the client 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%
So far, so good.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%
We, of course, can also make a connection using a web browser.
Of, course, we don't show the 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:
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
from Netscape (or some other browser):http://tucotuco.cs.indiana.edu:12345
Now we're getting so much closer: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%
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
using Netscape. Then the result is as follows.http://tucotuco.cs.indiana.edu:12345/one.html
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.
The output above was generated by calling the server three times: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%
One of the files is missing, hence the exception.http://tucotuco.cs.indiana.edu:12345/one.html http://tucotuco.cs.indiana.edu:12345/two.html http://tucotuco.cs.indiana.edu:12345/one.html
I have two more references for I/O and networking.
They're here:
http://www.cs.indiana.edu/classes/a348/CTED/moduleFour/lectures/Apr22.html)
http://www.cs.indiana.edu/classes/a348/CTED/moduleFour/lectures/Apr17.html)
And here's a very basic reference to
http://www.cs.indiana.edu/classes/a348/CTED/moduleFour/lectures/Apr10.html)