0% found this document useful (0 votes)
24 views

Objects and Client - Server Connections

This document summarizes a series of articles on object-oriented programming concepts using Java. It discusses how objects can be created on one machine and serialized to be sent over a network to another machine. The document reviews code from a previous article that implements a simple client-server example to demonstrate this. It describes how the client creates an Employee object, sends it to the server, the server modifies the object's attributes and returns it to the client. The document then discusses enhancements to the code that allow the server to handle multiple clients and transactions.

Uploaded by

Yashaswi Piplani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views

Objects and Client - Server Connections

This document summarizes a series of articles on object-oriented programming concepts using Java. It discusses how objects can be created on one machine and serialized to be sent over a network to another machine. The document reviews code from a previous article that implements a simple client-server example to demonstrate this. It describes how the client creates an Employee object, sends it to the server, the server modifies the object's attributes and returns it to the client. The document then discusses enhancements to the code that allow the server to handle multiple clients and transactions.

Uploaded by

Yashaswi Piplani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Architecture & Design  Objects and Client/Server Connections

Objects and Client/Server


Connections
By Matt Weisfeld  May 8, 2006

Developer.com content and product recommendations are editorially


independent. We may make money when you click on links to our
partners. Learn More.

This series, The Object-Oriented Thought Process, is intended for someone


just learning an object-oriented language and who wants to understand the
basic concepts before jumping into the code, or someone who wants to
understand the infrastructure behind an object-oriented language he or she
is already using. These concepts are part of the foundation that any
programmer will need to make the paradigm shift from procedural
programming to object-oriented programming.

Click here to start at the beginning of the series.

In keeping with the code examples used in the previous articles, Java will be
the language used to implement the concepts in code. One of the reasons
that I like to use Java is because you can download the Java compiler for
personal use at the Sun Microsystems Web site http://java.sun.com/. You can
download the standard edition, J2SE 5.0, at
http://java.sun.com/j2se/1.5.0/download.jsp to compile and execute these
applications. I often reference the Java J2SE 5.0 API documentation and I
recommend that you explore the Java API further. Code listings are provided
for all examples in this article as well as figures and output (when
appropriate). See the first article in this series for detailed descriptions for
compiling and running all the code examples.

In the previous column, we covered the basic Java technology required to


construct a simple client/server example. The example illustrated how an
object is constructed on one machine and then marshaled across a network
to another machine. The process involves serializing the object so that it can
be transferred across a wire and then reconstructed on the other side. In this
article, we will further explore the process of moving an object across a client-
server connection. Specifically, we will investigate what happens when the
× we
unexpected occurs. We will first review the client/server application that
began in the last column, and then we will throw in some wrinkles.
Running the Client/Server Example
First, let’s review the code from the last column. The examples in this article
extend this code, so it is important that you reach this baseline by compiling
and running the simple client server example (if you have not read the
previous column or would like to review it, please visit the following URL:
http://www.developer.com/db/article.php/3597071).

There are 3 files in this example, Employee.java, Server.java and Client.java.

The basic concept is this:

An Employee object is created

Attributes in the Employee object are set

The client sends Employee object is sent across a network

The server accepts the Employee object

The server changes the Employee object’s attributes

The server sends the Employee object back to the client

The client verifies that the attributes were indeed altered

The complete code for the Employee class is shown in Listing 1.

import java.io.*;
import java.util.*;

public class Employee implements Serializable {

private int employeeNumber;


private String employeeName;

Employee(int num, String name) {


employeeNumber = num;
employeeName= name;
}

public int getEmployeeNumber() {


return employeeNumber ;
}

public void setEmployeeNumber(int num) {


employeeNumber = num;
}

public String getEmployeeName() {


return employeeName ;
}
×
public void setEmployeeName(String name) {
employeeName = name;
}
}

Listing 1: The Employee Object

The complete code for the Client class is shown in Listing 2.

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

public class Client {

public static void main(String[] arg) {


try {
Employee joe = new Employee(150, "Joe");

System.out.println("employeeNumber= " + joe


.getEmployeeNumber());
System.out.println("employeeName= " + joe
.getEmployeeName());

Socket socketConnection = new Socket("127.0.0.1", 11111

ObjectOutputStream clientOutputStream = new


ObjectOutputStream(socketConnection
.getOutputStream());
ObjectInputStream clientInputStream = new
ObjectInputStream(socketConnection.getInputStream());

clientOutputStream.writeObject(joe);

joe= (Employee)clientInputStream.readObject();

System.out.println("employeeNumber= " + joe


.getEmployeeNumber());
System.out.println("employeeName= " + joe
.getEmployeeName());

clientOutputStream.close();
clientInputStream.close();

} catch (Exception e) {System.out.println(e); }


}
}

×
Listing 2: The Client
The complete code for the Server class is shown in Listing 3.

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

public class Server {

public static void main(String[] arg) {

Employee employee = null;

try {

ServerSocket socketConnection = new ServerSocket(11111)

System.out.println("Server Waiting");

Socket pipe = socketConnection.accept();

ObjectInputStream serverInputStream = new


ObjectInputStream(pipe.getInputStream());

ObjectOutputStream serverOutputStream = new


ObjectOutputStream(pipe.getOutputStream());

employee = (Employee )serverInputStream.readObject();

employee .setEmployeeNumber(256);
employee .setEmployeeName("John");

serverOutputStream.writeObject(employee);

serverInputStream.close();
serverOutputStream.close();

} catch(Exception e) {System.out.println(e);
}
}

Listing 3: The Server

×
Compiling and Running the System

Compiling the Code

I compiled the code using a DOS Shell. On certain machines it is called a DOS
Shell and on others it is called a Command Prompt. They and equivalent and I
will show examples of both. Eventually we will need two of these DOS Shells,
one to run the Server and one for the Client. You can open a DOS Shell in the
Programs->Accessories option.

Type the following code at the command prompt to compile all three of the
files.

"C:Program FilesJavajdk1.5.0_06binjavac" Employee.java


"C:Program FilesJavajdk1.5.0_06binjavac" Client.java
"C:Program FilesJavajdk1.5.0_06binjavac" Server.java

Figure 1 shows the screen shot of how this is accomplished.

Figure 1. Compiling the Code

Starting the Server

In one of the DOS Shells, type in the following line at the command prompt:

"C:Program FilesJavajdk1.5.0_06binjava" Server

Figure 2 shows what happens in the DOS Shell.

Figure 2 – Starting the Server


×
If everything is working properly, the “Server Waiting” message is displayed.
At this point, we can start the Client.

Starting the Client

In a separate DOS Shell, start the Client with the following line.

"C:Program FilesJavajdk1.5.0_06binjava" Client

The result is shown in Figure 3.

Figure 3 – Starting the Client

If all is well, you will see that the employeeNumber and the employeeName
both were changed. You can put some specific identification in the print
statements to provide further assurance.

With the circuit complete, the Server should exit cleanly, as shown in Figure 4.

Figure 4 – Completing the System

Resetting the Server


What we have created is a very simple client/server application using the Java
programming language. At this point, our server accepts a single transaction
×
from the client and then simply terminates. While this is fine for
demonstration purposes, it is not very useful. One of the more interesting
exercises that I use in the classroom has multiple clients connecting to the
same server. For this to occur, the server obviously must not terminate after
serving a single transaction.

Handling Multiple Clients

At a very basic level, there is a simple code enhancement that will allow the
Server to handle multiple clients. In fact, the server can also handle multiple
transactions from the same client. For example, by adding a simple while
loop, we can provide this behavior. Listing 4 contains this enhancement.

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

public class Server {

public static void main(String[] arg) {

Employee employee = null;

try {

ServerSocket socketConnection = new ServerSocket(111

while (true) {

System.out.println("Server Waiting");

Socket pipe = socketConnection.accept();

ObjectInputStream serverInputStream = new


ObjectInputStream(pipe.getInputS

ObjectOutputStream serverOutputStream =
ObjectOutputStream(pipe.getOutpu

employee = (Employee )serverInputStream.readObje

employee .setEmployeeNumber(256);
employee .setEmployeeName("John");

serverOutputStream.writeObject(employee);

serverInputStream.close();
serverOutputStream.close();

} // end of the while loop

×
} catch(Exception e) {System.out.println(e);
}
}

Listing 4: Resetting the Server

The two lines in bold represent the code required to implement the loop.
Note that several lines of the code must reside within the loop.

Note: In A Later Article We Will Explore Some Of The


Performance Issues That We Can Address In A Client/Server
Environment.

The basic concept here is that once the Server handles a single client
transaction, it closes the input/output stream and then loops back to wait for
the next client transaction. Each time the following line is encountered, the
Server simply waits.

Socket pipe = socketConnection.accept();

If no client is sending transactions, the Server blocks and waits to be notified.

The Sun documentation states the following regarding the ServerSocket


accept method:

Listens for a connection to be made to this socket and accepts it. The
method blocks until a connection is made.
A new Socket s is created and, if there is a security manager, the security
manager’s checkAccept method is called with
s.getInetAddress().getHostAddress() and s.getPort() as its arguments to
ensure the operation is allowed. This could result in a SecurityException.

To test the use of multiple clients, simply create more than one client. Make
sure that each client uses the IP address of the server and you are ready to
test. Figure 5 shows how my system looks when I am running the Server with
2 different clients.

Figure 5 – Multiple Clients

×
Identifying the Client

One very useful piece of information that the Server can collect is some sort
of client ID. We can actually embed this in the Employee object itself. This ID
can take the form of a simple ID number or we can inspect any attribute on
the object. In this example, rather than use the employeeNumber attribute,
let’s use the employeeName attribute. This will make it easier for us to read
and identify the client more easily.

We have already created an Employee object with the employeeName name


of Joe, so let’s create one with the employeeName of Mary. We can use the
following line of code in the 2nd client application.

Employee mary = new Employee(250, "Mary");

On the server side, we can add a line of code to print out the name of the
specific Employee object.

employee = (Employee )serverInputStream.readObje

System.out.println("Serving " + employee.getEmpl

Figure 6 shows what happens when we use two clients. The first Client has
the name of Joe and the second the name of Mary. You can see the specific
information printed in the client Command Prompt. The Server Command
Prompt is more interesting. Note that the Server handles the message from
both Joe and Mary and then prints their name. This illustrates that the Server
can indeed handle multiple clients. It is important to realize how nicely all of
this is packaged into the objects and how the objects are marshaled across
the network.

Figure 6 – Identifying Multiple Clients

Using another Machine on the Network

At this point, rather than using the loopback IP address (“127.0.0.1”), it is


interesting to find another computer on the network and connect to the
server from a different machine. There will be no change to the client code
except for updating the IP address. To find the specific IP address of the
machine, you can use the ipconfig command at the Command Prompt of the
Server.

×
C:column22cs> ipconfig
This command will provide the appropriate IP address for the server. Simply
change the loopback string, “127.0.0.1”, to the IP address of the Server.

Keeping things in Sync


Getting this client/server system to work requires that both sides use the
same classes. This may seem obvious, but it is easy for the two sides to
become out of sync. This has to do with one of the strengths of Java. As is
often the case, a specific strength can lead to some potentially significant
problems if you are not careful.

For example, let’s make a change to the Client. Let’s say that we want to add a
last name to the Employee object as seen in Listing 5.

import java.io.*;
import java.util.*;

public class Employee implements Serializable {

private String employeeLastName;


private int employeeNumber;
private String employeeName;

Employee(int num, String name) {


employeeNumber = num;
employeeName= name;
}

public int getEmployeeNumber() {


return employeeNumber ;
}

public void setEmployeeNumber(int num) {


employeeNumber = num;
}

public String getEmployeeName() {


return employeeName ;
}

public void setEmployeeName(String name) {


employeeName = name;
}
public String setEmployeeLastName() {
return employeeName ;
}

public void getEmployeeLastName(String name) {


employeeName = name; ×
}
}

Listing 5: The Employee with lastName added.

Note the lines in bold. These lines add the functionality of the lastName.
However, this obviously changes the Employee class. For example, if the
Client compiles on one machine with this change and the Server compiles on
another with the old version of Employee, a problem will arise (see Figure 7).

Figure 7 – Incompatible Employee Class

The Server reports the following exception:

java.io.InvalidClassException: Employee; local class incompatibl


esc serialVersionUID = -2555159439224478262, local class serialV
525241219380744

The Employee class the Server uses is different than the one that the Client
uses – and this is not allowed. The fact that this can even happen is because
Java dynamically loads all classes – there is no linked executable. This is a
tricky configuration management issue. If you update a class you must make
sure that all distributions of that class get updated.

In this example, the Employee class was updated on the Client, but not the
Server. Since the Server was expecting a specific Employee class, an exception
was generated when it received a different one. The interesting thing to look
at is the fact that a class is assigned a serialVersionUID. When these two
serialVersionUIDs do no match, a problem is identified. This is as much a
security issue as it is a programming issue.

The Sun documentation states the following regarding the serialVersionUID:

The serialization runtime associates with each serializable class a version


number, called a serialVersionUID, which is used during deserialization to
verify that the sender and receiver of a serialized object have loaded classes
for that object that are compatible with respect to serialization. If the
receiver has loaded a class for the object that has a different
serialVersionUID than that of the corresponding sender’s class, then
deserialization will result in an InvalidClassException.
×
Conclusion
In this article, we expanded upon the basic concepts involved with creating a
simple Client/Server model. The code is a complete and functional model.

As we have seen, moving an object from one place to another is often a tricky
proposition. In languages such as Java and the .Net languages, while the
ability to load objects dynamically is a major strength, we have to deal with
the problem of keeping the class versions in sync.

While the example of this article is complete and useful, it is quite basic. There
are many more fascinating topics to explore regarding client/server
applications.

References

Tyma, Paul, Gabriel Torok and Troy Downing: Java Primer Plus. The Waite
Group, 1996.

www.javasoft.com

About the Author

Matt Weisfeld is a faculty member at Cuyahoga Community College (Tri-C) in


Cleveland, Ohio. Matt is a member of the Information Technology
department, teaching programming languages such as C++, Java, and C#
.NET as well as various web technologies. Prior to joining Tri-C, Matt spent 20
years in the information technology industry gaining experience in software
development, project management, business development, corporate
training, and part-time teaching. Matt holds an MS in computer science and
an MBA in project management. Besides The Object-Oriented Thought
Process
, which is now in it’s second edition, Matt has published two other computer
books, and more than a dozen articles in magazines and journals such as Dr.
Dobb’s Journal, The C/C++ Users Journal, Software Development Magazine,
Java Report, and the international journal Project Management. Matt has
presented at conferences throughout the United States and Canada.

You might also like