[Stripped down versions of code below is here.]
0. Non-assignment. Next term we'll start with the material covered in the first section of Ch. 15 of Eckel (the section called "Network programming"), and then switch over to Marty Hall, Core Servlets and JavaServer Pages (Prentice-Hall, 0130893404), which will be the main text for the Java half of the second trimester of IPL.
1. Files
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("somefile.txt")));
// Copier.java
import java.io.*;
public class Copier {
public static void main(String[] args) {
String inFileName, outFileName, currentLine;
BufferedReader inFile;
PrintWriter outFile;
// All kinds of i/o errors can jump up and byte us--disk-full errors,
// non-existent files, you name it--so here and in the following files
// we basically wrap everything in a "try"
try {
System.out.println("I am a file copier");
// Let the user specify the file to be copied and the name of the output
// file. We can get the user's keystrokes from System.in, but System.in is
// a raw InputStream, so we convert it to something friendlier--something
// we can call readLine() on
BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter input filename:");
inFileName = keyIn.readLine();
System.out.println("Enter output filename:");
outFileName = keyIn.readLine();
keyIn.close();
// With the names in hand, we get the input and output streams of the
// corresponding files, and again turn them into more easily usable objects
inFile = new BufferedReader(new InputStreamReader(new FileInputStream(inFileName)));
outFile = new PrintWriter(new OutputStreamWriter(new FileOutputStream(outFileName)));
// now loop over the input object, reading a line at a time, and writing that
// value to the output object; readLine() is defined to return null when the
// input terminates
while ((currentLine = inFile.readLine()) != null)
outFile.println(currentLine);
// release the streams
inFile.close();
outFile.close();
}
catch (FileNotFoundException e) {
System.out.println("Couldn't get files.");
}
catch (IOException e) {
System.out.println("Bad i/o happened.");
}
}
}
2. Networks
// HelloClient.java
import java.net.*;
import java.io.*;
public class HelloClient {
private static final int SERVERPORT = 5555;
public static void main(String[] argv) {
try {
// Ask for a TCP connection, specifying server and service port; n.b. given
// a Socket object, the client can discover its own port, but usually it
// doesn't need to know this.
Socket conn = new Socket("bob.marlboro.edu", SERVERPORT);
// The socket acts like a file in that it has input and output streams associated
// with it; and as in the case of a file, for convenience we can convert the
// raw streams to other kinds of objects. Notice that the second argument to the
// PrintWriter constructor forces the PrintWriter to flush its buffer on each
// write.
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(conn.getOutputStream()), true);
// And here's the entire output from the client side: do a println() of a string
// into the PrintWriter associated with the network socket.
pw.println("Hi from client");
// And conversely, grab the one input line coming in from the server, and
// do a regular S.o.println() on it
System.out.println(br.readLine());
// And we close up shop
br.close();
pw.close();
conn.close();
}
catch (Exception e) { System.out.println("Oops."); }
}
}
// HelloServer.java
import java.net.*;
import java.io.*;
public class HelloServer {
private static final int PORT = 5555;
public static void main(String[] argv) {
try {
System.out.println("HelloServer running");
// Listen for TCP connection requests on the specified port (the second parameter
// to the constructor says how long a queue of pending connection requests to
// maintain)
ServerSocket s = new ServerSocket(PORT, 1);
// When a request comes in, set up the connection, and give us a regular Socket
// object for it
Socket conn = s.accept();
// As in the case of the client, convert the raw streams
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(conn.getOutputStream()), true);
// Input and output are also parallel to what the client does
pw.println("Hi from server");
System.out.println(br.readLine());
br.close();
pw.close();
conn.close();
}
catch (Exception e) { System.out.println("Oops."); }
}
}
// FileClient.java
import java.net.*;
import java.io.*;
public class FileClient {
private static final int SERVERPORT = 5556;
public static void main(String[] argv) {
String inFileName, s;
try {
System.out.println("I am a file fetcher");
// Get the filename
BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter name of file to fetch");
inFileName = keyIn.readLine();
// Open the connection to the server and convert the raw streams
Socket conn = new Socket("bob.marlboro.edu", SERVERPORT);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(conn.getOutputStream()), true);
// Send the filename to the server
pw.println(inFileName);
// Read the results line by line, and write them to the display (we could of
// course get a PrintWriter corresponding to a local file, and write the
// results there instead
while ((s = br.readLine()) != null)
System.out.println(s);
br.close();
pw.close();
conn.close();
}
catch (Exception e) { System.out.println("Oops."); }
}
}
// FileServer.java
import java.net.*;
import java.io.*;
public class FileServer {
private static final int PORT = 5556;
public static void main(String[] argv) {
String inFileName, currentLine;
try {
System.out.println("FileServer running");
// Listen for inbound connections, when one comes in, get the Socket object for it,
// and convert the streams of that socket
ServerSocket s = new ServerSocket(PORT, 1);
Socket conn = s.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(conn.getOutputStream()), true);
// Get the filename from the client
inFileName = br.readLine();
// Get an input stream for the corresponding file and turn it into a BufferedReader
BufferedReader inFile = new BufferedReader(new InputStreamReader(new FileInputStream(inFileName)));
// Read the file line by line, and write it back over the network
while ((currentLine = inFile.readLine()) != null)
pw.println(currentLine);
br.close();
pw.close();
inFile.close();
conn.close();
}
catch (Exception e) { System.out.println("Oops."); }
}
}
// ThreadedFileServer.java
import java.net.*;
import java.io.*;
public class ThreadedFileServer extends Thread {
private static final int PORT = 5556;
private Socket mySocket;
BufferedReader br;
PrintWriter pw;
// Constructor for the current thread
public ThreadedFileServer(Socket conn) {
// Store the identity of your connection
mySocket = conn;
try {
// Turn its streams into a reader and writer
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
pw = new PrintWriter(new OutputStreamWriter(conn.getOutputStream()), true);
}
catch (IOException e) { System.exit(0); }
// Start yourself up
start();
}
public void run() {
String currentLine;
try {
// The code here is basically identical to what was in main() in
// FileServer.java: get the filename from the network client; turn that into a
// BufferedReader for the corresponding file; read the lines from that file and
// write them back to the client
String inFileName = br.readLine();
BufferedReader inFile = new BufferedReader(new InputStreamReader(new FileInputStream(inFileName)));
while ((currentLine = inFile.readLine()) != null)
pw.println(currentLine);
br.close();
pw.close();
inFile.close();
mySocket.close();
}
catch (IOException ioe) { System.exit(0); }
}
public static void main(String[] argv) {
try {
System.out.println("FileServer running");
// Listen
ServerSocket s = new ServerSocket(PORT, 1);
// Do this forever: get a new connection, then make an instance of the current
// class to handle it
while (true) {
Socket conn = s.accept();
new ThreadedFileServer(conn);
}
}
catch (IOException e) { System.out.println(e); }
}
}
// ThreadedProcessingServer.java
import java.net.*;
import java.io.*;
public class ThreadedProcessingServer extends Thread {
private static final int PORT = 5556;
private Socket mySocket;
BufferedReader br;
PrintWriter pw;
// Same as in ThreadedFileServer
public ThreadedProcessingServer(Socket conn) {
mySocket = conn;
try {
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
pw = new PrintWriter(new OutputStreamWriter(conn.getOutputStream()), true);
}
catch (IOException e) { System.exit(0); }
start();
}
// Same as in ThreadedFileServer, except that instead of assuming that the
// string we get from the client is always going be the name of a static file
// (and building a BufferedReader immediately for that file), we call
// getInputSource(), which will figure out the right thing to do for this
// particular string, and give us back the appropriate BufferedReader
public void run() {
String currentLine;
try {
String inFileName = br.readLine();
BufferedReader inputSource = getInputSource(inFileName);
while ((currentLine = inputSource.readLine()) != null)
pw.println(currentLine);
br.close();
pw.close();
inputSource.close();
mySocket.close();
}
catch (IOException ioe) { System.exit(0); }
}
// Construct and return a BufferedReader, given a string filename. If
// the filename looks like it's for a Perl executable, run that executable and
// build a BufferedReader that's attached to the output of that process.
// Otherwise assume you're just dealing with an ordinary file, and build
// a BufferedReader for it.
public BufferedReader getInputSource(String fileName) {
try {
// Pretty crude: if the file extension looks distinctive...
if (fileName.endsWith(".pl")) {
// Runtime.getRuntime() returns a Runtime object that lets us interface with
// our, um, runtime environment; given that object, we can run programs
// in our environment via the exec() method; exec() returns a Process object
// that we can use to access and control this external program that we've
// started--in the present case what we're going to want to do is grab
// the data streaming out of it
Runtime rt = Runtime.getRuntime();
// Just for fun: the ThreadedProcessingServer communicates with external
// programs using the Who Gateway Interface: when it executes an external
// program, the TPS sets up certain environment variables for that program.
// In version 0.00001, the Who Gateway Interface stipulates that the server
// will set up an environment variable called WHO, whose value is the
// domain name of the network client.
String[] env = {"WHO=" + mySocket.getInetAddress().getHostName()};
Process p = rt.exec(fileName, env);
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
else {
// This is just what we did in the previous case: turn the filename
// directly into a BR
return new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
}
}
catch (IOException ioe) { return null; }
}
// Same as in ThreadedFileServer
public static void main(String[] argv) {
try {
System.out.println("FileServer running");
ServerSocket s = new ServerSocket(PORT, 1);
while (true) {
Socket conn = s.accept();
new ThreadedProcessingServer(conn);
}
}
catch (IOException e) { System.out.println(e); }
}
}
// Here's an example of what the Perl side of the Who Gateway Interface might look like
#!/usr/bin/perl
print "Hi there at: " . $ENV{"WHO"} . "\n";