Some of the general characteristics of clients and server applications are, in general, client applications have the following characteristics:
They are applications that become a client temporarily when remote acces is needed, but perform other computation locally.
They are invoked by a user and execute for one session.
They run locally on the user's local computer.
They actively initiate contact with a server and so must know the server details.
They can access multiple services as required.
In general, server applications have the following characteristics:
They are special-purpose applications dedicated to providing one service.
They are invoked automatically when a system boots, and continue to execute through many sessions.
They generally run on a shared computer.
They wait passively for contact from remote clients.
They accept contact from clients, but offer a single service.
Note that the word server here is referring to a piece of software. However, a computer running one or more server applications is often also referred to as a server.
We will now write a client/server application pair where:
The Client will take some data from the user and validate it (as in Finger)
The Client will then send this data to the Server for processing (as in Finger)
The Server will process the data and return the results
The Client will receive the results and display the results in some form.
For our example here We will do this by building a Date/Time Service. The client will simply call the server and ask it for the current date and time.
The Date Server is possibly the most complex part of this application, in this case consisting of three main classes:
The 
DateTimeService class - A basic class to get the current
date and time when it is called
The 
HandlerConnection class - This class is used to handle any
requests that arrive to the DateServer. This class is specially designed to allow a later transition
to a threaded server.
The 
DateServer class - This is the main server application, that
simply listens for connections and creates a 
HandlerConnection object when
a connection occurs to the server
We will choose the port 5050 as the port to which we send and listen to for our service. Both a client and a server need to create their own sockets. On the server we listen to port 5050.
The Date Client is very similar to the Finger client we looked at in the section called “The Finger Client” except that the data transfer uses an Object Stream to send and receive data - we will discuss this later.
We will first discuss what occurs in the client/server application before looking directly at the code.
First off, the server is started by typing the command java DateServer on the physical
server machine. The 
DateServer starts and begins listening for connections on port 5050.
In Figure 10.6, “The Date Client Creates a Connection to the Date Server.” the 
DateClient class is executed by using the
command java DateClient theServer where theServer is the hostname of the physical
machine on which the 
DateServer class is located. The 
DateClient
creates a socket and connects to the 
DateServer server socket running at port
5050. The 
DateServer should accept this connection provided it is not busy.
Next, as in Figure 10.7, “The Date Server creates a HandleConnection object.” the 
DateServer class creates a

HandleConnection object to which it passes a reference to the 
DateClient's
socket details. The 
HandleConnection class then creates an instance of the

DateTimeService. It also establishes an input/output stream to the

DateClient.
Next, as in Figure 10.8, “The Date Client passes the command to the HandleConnection.” the 
DateClient passes a command
to the 
HandleConnection. In this case the command is a 
String
object that contains the text "GetDate". When the 
HandleConnection
receives the 
String object it compares it to see if it is a valid command. In our case
the only valid command is "GetDate" so if it is this command then the 
DateTimeService
is called to request the date/time. At this time, since we have not threaded our server application the

DateServer is not actually listening to port 5050, rather it is waiting for a response
from the 
HandleConnection object.
in Figure 10.9, “The HandleConnection gets the Date/Time and sends it to the Client.” the 
DateTimeService sends the data/time details
back to the 
HandleConnection object where it is then passed on to the

DateClient as a 
String object such as "Mon 15th...".
The 
DateClient will then display the returned data on the client's machine.
Finally as in Figure 10.10, “The HandleConnection shuts down. The DateServer starts listening again.” the 
HandleConnection object shuts
down connection and is destroyed. Control is returned to the 
DateServer class and the server once
again begins listening to port 5050. The client is now disconnected after having received the data. It now
shuts down in our case. The next client is now free to connect to port 5050 on the 
DateServer
and everything happens again. The 
DateServer will listen forever unless we shut it down
by typing CTRL-C in the terminal window.
Here you can see the client and server applications working as if you executed them from the command
prompt. The 
DateServer is executed by typing java DateServer. There
is no need to specify a port number as 5050 is hard coded and there is no need to specify a host name as the
code will use the current machine as the server. Figure 10.11, “The DateServer running on "localhost"” shows the

DateServer being executed and it stating that it has "started listening on port 5050".
The server then accepts 3 different connections from three clients that request the time. You will notice
that there is 10 seconds between each call.
Figure 10.12, “The Date Client specifing a server at "localhost"” displays the 
DateClient running
four times. The first time that the client was run the server name was not specified, so the error was
displayed. The next time the client was executed correctly using java DateClient localhost
where the server is specified as being on the same machine (we could also have typed 127.0.0.1 instead of
localhost). The client connects to the server and received that the date is
Wed Jul 16 15:13:18 BST 2003. The client disconnected and shut down. The client was
executed two further times at 10 second intervals.
There are four classes required for this example, as listed below. Download these classes into the one
directory - e.g. c:\temp on your machine and compile them by typing
javac *.java. Once they have compiled successfully then open a second DOS/Unix command
prompt/terminal and execute the server in one by typing java DateServer and execute the
client in the second command prompt/server by typing java DateClient localhost where
both applications are on the one machine. If you want to run the client on another PC simply execute it
using java DateClient the.server.name where the.server.name is the IP/DNS name of the
machine on which the server is running.
Here is the source code for the 
DateTimeService class that provides the date and
time to the 
HandleConnection class - as below and as in
DateTimeService.java
1
2
3
4 // The DateTimeService class that provides the current date
5 // by Derek Molloy.
6
7 import java.util.*;
8
9 public class DateTimeService
10 {
11 private Date theDate;
12
13 //constructor gets the current date/time
14
15 public DateTimeService()
16 {
17 this.theDate = new Date();
18 }
19
20 //method returns date/time as a formatted string
21
22 public String getDateAndTime()
23 {
24 return "The date is:" + this.theDate.toString();
25 }
26 }
27
28 Here is the source code for the 
DateServer class that runs the server application
and creates an instance of the 
HandleConnection whenever a connection is made by
a client - as below and as in
DateServer.java
1
2
3
4 // The DateServer - The server application that passes control
5 // to the Handle Connection - by Derek Molloy
6
7 import java.net.*;
8 import java.io.*;
9
10 public class DateServer
11 {
12 public static void main(String args[])
13 {
14 ServerSocket serverSocket = null;
15 try
16 {
17 serverSocket = new ServerSocket(5050);
18 System.out.println("Server has started listening on port 5050");
19 }
20 catch (IOException e)
21 {
22 System.out.println("Error: Cannot listen on port 5050: " + e);
23 System.exit(1);
24 }
25 while (true) // infinite loop - loops once for each client
26 {
27 Socket clientSocket = null;
28 try
29 {
30 //waits here (forever) until a client connects
31 clientSocket = serverSocket.accept();
32 System.out.println("Server has just accepted socket
33 connection from a client");
34 }
35 catch (IOException e)
36 {
37 System.out.println("Accept failed: 5050 " + e);
38 break;
39 }
40
41 // Create the Handle Connection object - only create it
42 HandleConnection con = new HandleConnection(clientSocket);
43
44 if (con == null) //If it failed send and error message
45 {
46 try
47 {
48 ObjectOutputStream os = new ObjectOutputStream(
49 clientSocket.getOutputStream());
50 os.writeObject("error: Cannot open socket thread");
51 os.flush();
52 os.close();
53 }
54 catch (Exception ex) //failed to even send an error message
55 {
56 System.out.println("Cannot send error back
57 to client: 5050 " + ex);
58 }
59 }
60 else { con.init(); } // otherwise we have not failed to
61 // create the HandleConnection object
62 // run it now.
63 }
64 try // do not get here at the moment
65 {
66 System.out.println("Closing server socket.");
67 serverSocket.close();
68 }
69 catch (IOException e)
70 {
71 System.err.println("Could not close
72 server socket. " + e.getMessage());
73 }
74 }
75 }
76
77 Here is the source code for the 
HandleConnection class that is created by
the 
DateServer class whenever a connection is received. This class is responsible
for dealing with each of the client requests.
HandleConnection.java
1
2
3 // The Handle connection class - that deals will all client requests
4 // directly - by Derek Molloy
5
6 import java.net.*;
7 import java.io.*;
8 import java.util.*;
9
10
11 public class HandleConnection
12 {
13
14 private Socket clientSocket; // Client socket object
15 private ObjectInputStream is; // Input stream
16 private ObjectOutputStream os; // Output stream
17 private DateTimeService theDateService;
18
19 // The constructor for the connecton handler
20
21 public HandleConnection(Socket clientSocket)
22 {
23 this.clientSocket = clientSocket;
24
25 //Set up a service object to get the current date and time
26 theDateService = new DateTimeService();
27 }
28
29 // The main execution method
30 public void init()
31 {
32 String inputLine;
33
34 try
35 {
36 this.is = new ObjectInputStream(clientSocket.getInputStream());
37 this.os = new ObjectOutputStream(clientSocket.getOutputStream());
38 while (this.readCommand()) {}
39 }
40 catch (IOException e)
41 {
42 e.printStackTrace();
43 }
44 }
45
46 // Receive and process incoming command from client socket
47
48 private boolean readCommand()
49 {
50 String s = null;
51
52 try
53 {
54 s = (String)is.readObject();
55 }
56 catch (Exception e)
57 {
58 s = null;
59 }
60 if (s == null)
61 {
62 this.closeSocket();
63 return false;
64 }
65
66 // invoke the appropriate function based on the command
67 if (s.equals("GetDate"))
68 {
69 this.getDate();
70 }
71 else
72 {
73 this.sendError("Invalid command: " + s);
74 }
75 return true;
76 }
77
78 private void getDate() // uses the date service to get the date
79 {
80 String currentDateTime = theDateService.getDateAndTime();
81 this.send(currentDateTime);
82 }
83
84
85 // Send a message back through to the client socket as an Object
86 private void send(Object o)
87 {
88 try
89 {
90 System.out.println("Sending " + o);
91 this.os.writeObject(o);
92 this.os.flush();
93 }
94 catch (Exception ex)
95 {
96 ex.printStackTrace();
97 }
98 }
99
100 // Send a pre-formatted error message to the client
101 public void sendError(String msg)
102 {
103 this.send("error:" + msg); //remember a string IS-A object!
104 }
105
106 // Close the client socket
107 public void closeSocket() //close the socket connection
108 {
109 try
110 {
111 this.os.close();
112 this.is.close();
113 this.clientSocket.close();
114 }
115 catch (Exception ex)
116 {
117 System.err.println(ex.toString());
118 }
119 }
120 }
121
122
123 Here is the source code for the 
DateClient class that is the only class
required on the client side. It connects to the server and requests the date/time.
DateClient.java
1
2
3
4 // The Date Client - The date client connects to the server, sends
5 // the "GetDate" command and waits for a response - by Derek Molloy
6
7 import java.net.*;
8 import java.io.*;
9 import java.util.*;
10
11 public class DateClient
12 {
13
14 private Socket socket = null;
15 private ObjectOutputStream os = null;
16 private ObjectInputStream is = null;
17
18 // the constructor expects the IP address of the server - the
19 // port is fixed at 5050
20 public DateClient(String serverIP)
21 {
22 if (!connectToServer(serverIP))
23 {
24 System.out.println("Cannot open socket connection...");
25 }
26 }
27
28 private boolean connectToServer(String serverIP)
29 {
30 try // open a new socket to port: 5050 and create streams
31 {
32 this.socket = new Socket(serverIP,5050);
33 this.os = new ObjectOutputStream(this.socket.getOutputStream());
34 this.is = new ObjectInputStream(this.socket.getInputStream());
35 System.out.print("Connected to Server\n");
36 }
37 catch (Exception ex)
38 {
39 System.out.print("Failed to Connect to Server\n" + ex.toString());
40 System.out.println(ex.toString());
41 return false;
42 }
43 return true;
44 }
45
46 private void getDate()
47 {
48 String theDate;
49 System.out.println("GetDate");
50 this.send("GetDate");
51 theDate = (String)receive();
52 if (theDate != null)
53 {
54 System.out.println("The Server's date is " + theDate);
55 }
56 }
57
58 // method to send a generic object.
59 private void send(Object o)
60 {
61 try
62 {
63 System.out.println("Sending " + o);
64 os.writeObject(o);
65 os.flush();
66 }
67 catch (Exception ex)
68 {
69 System.out.println(ex.toString());
70 }
71 }
72
73 // method to receive a generic object.
74 private Object receive()
75 {
76 Object o = null;
77 try
78 {
79 o = is.readObject();
80 }
81 catch (Exception ex)
82 {
83 System.out.println(ex.toString());
84 }
85 return o;
86 }
87
88 public static void main(String args[])
89 {
90 if(args.length>0)
91 {
92 DateClient theApp = new DateClient(args[0]);
93 try
94 {
95 theApp.getDate();
96 }
97 catch (Exception ex)
98 {
99 System.out.println(ex.toString());
100 }
101 }
102 else
103 {
104 System.out.println("Error: you must provide the IP of the server");
105 System.exit(1);
106 }
107 System.exit(0);
108 }
109 }
110
111
112 © 2006
Dr. Derek Molloy
(DCU).