Java removes much of the complexity of writing Network aware applications, by providing a
Socket
class (java.net.Socket
). The socket is the software
abstraction, used to represent the terminals of a connection between two machines. The basic concept
is that you have two sockets on two machines and you create a connection between these sockets, that
you use to transfer data. We don't care how the data gets from one socket to another, even though
it might have to traverse many network hardware types (hence the abstraction).
We are going to write a finger client to demonstrate how TCP works in Java.
Finger is a standard service that allows a remote machine to query a server and ask it for information on a particular user, or on the users that are logged on. Most UNIX systems support finger, however on many server systems it is disabled, as it provides a little bit too much information for potential 'hackers'.
The host server is usually located at port 79, where a request is usually made up of a username followed by the '\n' character. The server sends any information back to the client and then terminates the connection.
Here is the source for Finger.java
that connects to any finger server and receives the output:
1 2 3 // TCP finger client - Derek Molloy... 4 // Usage: Finger username@host.com 5 6 import java.io.*; 7 import java.net.*; 8 9 public class Finger 10 { 11 public static void main ( String args[] ) 12 { 13 // Check command line paramaters 14 15 if (args.length != 1) 16 { 17 System.err.println ("Invalid number of paramaters:"); 18 System.err.println ("Usage: Finger username@host"); 19 System.exit(1); 20 } 21 // Check for existence of @ in paramater 22 else if (args[0].indexOf("@") == -1) 23 { 24 System.err.println ("Invalid paramater : syntax user@host"); 25 System.exit(1); 26 } 27 28 // Split command line paramater at the @ character 29 String username = args[0].substring(0, args[0].indexOf("@") ); 30 String hostname = args[0].substring(args[0].indexOf("@") +1, 31 args[0].length()); 32 try 33 { 34 System.out.println ("Connecting to " + hostname); 35 36 // Create a connection to server 37 Socket s = new Socket(hostname, 79); 38 39 // Create input and output streams to socket 40 PrintStream out = new PrintStream( s.getOutputStream()) ; 41 42 BufferedReader in = new BufferedReader( 43 new InputStreamReader( s.getInputStream())); 44 45 46 // Write username to socket output 47 out.println( username ); 48 49 // Read response from socket 50 String line = in.readLine(); 51 52 while (line != null) 53 { 54 System.out.println ( line ); 55 56 // Read next line 57 line = in.readLine(); 58 } 59 60 // Terminate connection 61 s.close(); 62 } 63 catch (SocketException e ) 64 { 65 System.err.println ("Socket error : " + e); 66 } 67 catch (UnknownHostException e ) 68 { 69 System.err.println ("Invalid host!"); 70 } 71 catch (IOException e ) 72 { 73 System.err.println ("I/O error : " + e); 74 } 75 } 76 } 77 78
When the Finger application is run it expects the name of a user@host, either specified by the full Internet name, or the name of a machine on the same network segment. If you forget to provide the parameters, it prompts you for the correct parameters (See Figure 10.3, “Finger Client Example”)
I have run the finger application three times in Figure 10.3, “Finger Client Example”. The first time
I omitted the parameter by typing java Finger and I was then prompted for the correct
parameter. In the second case I typed java Finger molloyd@khumbu.eeng.dcu.ie and this
searches for the username molloyd
at the hostname khumbu.eeng.dcu.ie
(a Unix server in the school with a finger server installed) and this returns details about this user. In
the third case I omitted the username and just typed java Finger @khumbu.eeng.dcu.ie. The
finger server is designed in this case to return a list of users that are currentl logged on, and the locations
where they are logged on from. Note: Khumbu may not accept connections from clients outside
of DCU for security reasons. So the process that occurs to get the output as in
Figure 10.3, “Finger Client Example” is sumarised in Figure 10.4, “Finger Client/Server Process”
The Finger application consists of three main steps:
Import the Network API and I/O packages. Add the main()
method
that is responsible for all the coding. Receive the parameters from the command line
args[]
and extract the username and hostname from a String
object of the form "user@some.host.com"
.
Connect to the server that runs on port 79 (The standard finger protocol port). Try to
catch any exceptions that may occur, such as SocketException
if the
socket does not establish correctly, UnknownHostException
if the host
is invalid and otherwise if an error occurs during reading/writing a general
IOException
may occur.
After establishing the connection. Write the output to the server and then read
in the input stream. For the output stream in this case I use a
PrintStream
that provides convenient functionality over and above the
standard OutputStream
such as the println()
method that we use. To create the PrintStream
object we pass the standard
OutputStream
object to its constructor. For reading the reply from the
server we use the BufferedReader
class. Before the current JDK we would have
used the InputStreamReader
but there was an error in the way that the
readLine()
was used, and so we must use the BufferedReader
class. This class provides the extra functionality on top of the standard InputStream
such as the readLine()
that we need for this application.
Another example of a client application is a basic web browser. This application allows you to connect to any web server (depending on your proxy) and request a web page. The result is returned in HTML and displayed in the text area as shown below
This application connects to a web site on port 80 and sends the string GET /index.html \n\n
where
index.html
is the page entered in the visual interface. It then reads the response from the server and
outputs to the text area.
Here is the source for BasicWebBrowser.java
that connects to any finger server and receives the output:
1 2 import java.awt.*; 3 import java.awt.event.*; 4 import java.io.*; 5 import java.net.*; 6 7 /** 8 * @author Derek Molloy 9 */ 10 11 public class BasicWebBrowser extends Frame implements ActionListener { 12 13 private TextField hostname, page; 14 private TextArea returnPage; 15 16 public BasicWebBrowser() 17 { 18 super("Basic Web Browser Application"); 19 20 this.setLayout(new FlowLayout()); 21 22 hostname = new TextField("www.eeng.dcu.ie",40); 23 this.add(new Label("SITE")); 24 this.add(hostname); 25 page = new TextField("index.html", 40); 26 this.add(new Label("Page:")); 27 this.add(page); 28 29 returnPage = new TextArea(10,40); 30 this.add(returnPage); 31 32 Button go = new Button("GO"); 33 go.addActionListener(this); 34 this.add(go); 35 this.setSize(400,350); 36 this.setVisible(true); 37 } 38 39 public void actionPerformed(ActionEvent e) { 40 41 Socket httpSocket = null; 42 DataOutputStream os = null; //output stream 43 DataInputStream is = null; //input stream 44 BufferedReader br = null; // buffered reader for correct reading 45 46 47 try { 48 httpSocket = new Socket(this.hostname.getText(), 80); //HTTP port 80 49 os = new DataOutputStream(httpSocket.getOutputStream()); 50 is = new DataInputStream(httpSocket.getInputStream()); 51 br = new BufferedReader(new InputStreamReader(is)); 52 } catch (UnknownHostException ex) { 53 System.err.println("Don't know host: " + this.hostname.getText()); 54 } catch (IOException ex) { 55 System.err.println("No I/O for the connection to: " + this.hostname.getText()); 56 } 57 58 if (httpSocket != null && os != null && is != null) 59 { 60 try 61 { 62 this.returnPage.append("Sending Request\n"); 63 String theRequest = new String("GET /" + this.page.getText() + "\n\n"); 64 returnPage.append(theRequest); 65 os.writeBytes(theRequest); 66 67 this.returnPage.append("Request Sent\n"); 68 // keep reading from/to the socket till we receive "Ok" 69 // from HTTP server. Once received then break. 70 71 String responseLine; 72 while ((responseLine = br.readLine()) != null) { 73 this.returnPage.append(responseLine); 74 if (responseLine.indexOf("Ok") != -1) { 75 break; 76 } 77 } 78 this.returnPage.append("End of Response\n"); 79 os.close(); 80 is.close(); 81 httpSocket.close(); 82 } 83 catch (UnknownHostException ex) { 84 System.err.println("Trying to connect to unknown host: " + ex); 85 } 86 catch (IOException ex) { 87 System.err.println("IOException: " + ex); 88 } 89 } 90 } 91 92 public static void main(String args[]) { 93 new BasicWebBrowser(); 94 } 95 } 96
© 2006 Dr. Derek Molloy (DCU).