Networking in Java
Networking in Java
Sockets
Computers running on the Internet communicate with each other using
either the Transmission Control Protocol (TCP) or the User Datagram
Protocol (UDP).
When you write Java programs that communicate over the network, you
are programming at the application layer.
Typically, you don't need to concern yourself with the TCP and UDP
layers.
Instead, you can use the classes in the java.net package.
These classes provide system-independent network communication.
However, to decide which Java classes your programs should use, you do
need to understand how TCP and UDP differ.
Sockets…
TCP is a connection-based protocol that provides a reliable flow of data
between two computers.
When two applications want to communicate to each other reliably, they
establish a connection and send data back and forth over that connection.
TCP guarantees that data sent from one end of the connection actually gets
to the other end and in the same order it was sent.
Otherwise, an error is reported.
HTTP, FTP, and Telnet are all examples of applications that require a
reliable communication channel.
UDP is a protocol that sends independent packets of data, called
datagrams, with no guarantees about arrival.
UDP is not connection-based unlike TCP.
For many applications, the guarantee of reliability is critical to the success
of the transfer of information from one end of the connection to the other.
Sockets…
However, other forms of communication don't require such strict standards.
In fact, they may be slowed down by the extra overhead or the reliable
connection may invalidate the service altogether.
Ports
Generally speaking, a computer has a single physical connection to the
network.
All data destined for a particular computer arrives through that connection.
However, the data may be intended for different applications/servers
running on the computer.
So how does the computer know to which application to forward the data?
Through the use of ports.
Data transmitted over the Internet is accompanied by addressing
information that identifies the computer and the port for which it is
Sockets…
The computer is identified by its 32-bit IP address, which IP uses to deliver
data to the right computer on the network.
Ports are identified by a 16-bit number, which TCP and UDP use to deliver
the data to the right application.
boolean isBound() It returns the binding state of the ServerSocket. It returns true if the
ServerSocket has ever been bound to a port.
It listens for a connection to be made to this socket and accepts it. The
Socket accept() method blocks until a connection is made. It throws IOException if an
I/O error occurs when waiting for a connection.
boolean isClosed() Returns the closed state of the ServerSocket. It returns true if the socket
has been closed.
Closes this server socket. Any thread currently blocked in
void close() ServerSocket.accept() will throw a SocketException. It throws
IOException if an I/O error occurs when closing the socket.
Sets the default receive buffer size for sockets accepted by the server
setReceiveBufferSize(int size) socket. This controls the suggested send buffer size used for
network input.
int getReceiveBufferSize() Returns the value of the buffer size that will be used for Sockets
accepted from this ServerSocket.
TCP Server Sockets…
Example: creating a server that listens for clients on port 4444
ServerSocket servSocket;
try {
servSocket = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
System.exit(-1);
}
ServerSocket provides a system-independent implementation of the server
side of a client-server socket connection.
The constructor for ServerSocket throws an exception if it can't listen on
the specified port (for example, the port is already being used).
If the server successfully binds to its port, then the ServerSocket object is
successfully created and the server continues to accept a connection from a
ServerSocket has a method called accept(), which is a blocking call that will
wait for a client to initiate connections
It then return a normal Socket that is then used for communication with the
client.
The accept() method returns a Socket object connecting the client and the
server.
Example: accepting client request on the server after creating the listener
ServerSocket servSocket ;
Socket socket = null;
try {
servSocket = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
System.exit(-1);
}
try {
socket = servSocket.accept();
} catch (IOException e) {
System.out.println("Accept failed: 4444");
System.exit(-1);
TCP Server Sockets…
Server manages each client connection with a Socket object.
After binding the server to a port with a ServerSocket, the server listens
indefinitely (or blocks) for an attempt by a client to connect.
To listen for a client, the program calls accept() method of ServerSocket as
in
Socket connection = server.accept();
This statement returns a Socket object when a connection with a client is
established.
TCP Server Sockets…
If you’re finished with a server socket, you should close it, especially if the
program is going to continue to run for some time.
This frees up the port and other programs may use it if necessary.
Closing a ServerSocket should not be confused with closing a Socket.
Closing a ServerSocket frees a port on the local host and it also breaks all
currently open sockets that the ServerSocket has accepted.
Server sockets are closed automatically when a program dies, so it’s not
absolutely necessary to close them.
Nonetheless, it is a good practice to close the socket before the program
ends.
Programmers often follow the approach “close if-not-null” in finally block.
TCP Server Sockets…
Example: closing ServerSocket
ServerSocket server = null;
try {
server = new ServerSocket(port);
//work with the server socket
} finally {
if (server != null) {
try {
server.close();
} catch (IOException ex) {
//ignore
}
}
Client Connection
A socket is a connection between two hosts.
The Socket class is Java’s fundamental class for performing client-side TCP
operations.
Other client-oriented classes that make TCP network connections such as URL,
URLConnection, HttpURLConnection, Applet, and JEditorPane all ultimately end
up invoking the methods of this class.
The Socket class itself uses native code to communicate with the local TCP stack of
the host operating system.
Socket can perform four basic operations: connect to a remote machine, send data,
receive data, and close a connection.
Java programs normally use client sockets in the following fashion:
the program creates a new socket using a constructor
Once connection established, the local and remote hosts get input and output
streams from the socket and use those streams to send data to each other.
The connection established by Socket is full-duplex where both hosts can send and
receive data simultaneously.
Client Connection…
The Socket class constructor specifies the host and the port to connect to.
Hosts may be specified as an InetAddress or a String.
Remote ports are specified as int values from 1 to 65535:
Socket(String host, int port) throws UnknownHostException, IOException
Socket(InetAddress host, int port) throws IOException
These constructors connect the server socket i.e. an active network connection is
established to the remote host.
If the connection can’t be opened for some reason, the constructor throws an
IOException or an UnknownHostException.
Example: client connection to a server
try {
Socket ss = new Socket("10.140.150.20", 80);
// send and receive data...
} catch (UnknownHostException ex) {
System.err.println(ex);
Client Connection…
Once Socket is created, it is possible to start sending and receiving data
after that.
If the socket cannot be opened for some reason, the constructor throws an
IOException.
There are many reasons a connection attempt might fail: the host you’re
trying to reach may not accept connections on that port, or routing
problems may be preventing your packets from reaching their destination.
Because this constructor doesn’t just create a Socket object but also tries to
connect the socket to the remote host, you can use the object to determine
whether connections to a particular port are allowed.
Using this, you can write a port scanner that checks which ports are
occupied and which ports are available.
Method Description
It returns an input stream for reading bytes from this socket. IOException - if an I/O
InputStream getInputStream() error occurs when creating the input stream, the socket is closed, the socket is not
connected, or the socket input has been shutdown.
It returns an output stream for writing bytes to this socket. It throws IOException if
OutputStream getOutputStream() an I/O error occurs when creating the output stream or if the socket is not
connected.
Returns the connection state of the socket. Returns true if the socket was
boolean isConnected()
successfully connected to a server
Closes this socket. Any thread currently blocked in an I/O operation upon this socket
void close()
will throw a SocketException.
boolean isClosed() Returns the closed state of the socket. Returns true if the socket has been closed.
Returns whether the read-half of the socket connection is closed. Returns true if the
boolean isInputShutdown()
input of the socket has been shutdown.
Returns whether the write-half of the socket connection is closed. Returns true if the
boolean isOutputShutdown()
output of the socket has been shutdown.
int getPort() Returns the remote port number to which this socket is connected.
int getLocalPort() Returns the local port number to which this socket is bound.
It returns the remote IP address to which this socket is connected, or null if the
InetAddress getInetAddress()
socket is not connected.
InetAddress getLocalAddress() Gets the local address to which the socket is bound.
The method suggests a number of bytes to use for buffering output on this socket.
setSendBufferSize(int size)
The OS is free to ignore this suggestion.
int getSendBufferSize() Returns the value of the buffer size used by the platform for output on this Socket.
The method suggests a number of bytes to use for buffering input from this socket.
setReceiveBufferSize(int size)
However, the underlying implementation is free to ignore this suggestion.
int getreceiveBufferSize() It returns the actual size of the receive buffer.
private ServerSocket serverSocket;
Example: server side that waits for clients to
public ServerListening() {
connect to it
try {
serverSocket = new ServerSocket(110);
startServer();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public void startServer() {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
while (true) {
try {
Socket socket = serverSocket.accept();
System.out.println("Just connected to " + socket.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(socket.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("Thank you for connecting to " + socket.getLocalSocketAddress());
out.writeUTF("\nGoodbye!");
socket.close();
}catch (IOException e) {
e.printStackTrace(); break;
}
Example: a client program that connects to a server by using a socket and sends a
greeting, and then waits for a response.
public class ClientConnection {
public static void main(String[] args) {
String serverName = "10.120.130.140";
int port = 110;
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from client");
To see the local port on the client, you can write the following code on the
client side
System.out.println("local port: " + socket.getLocalPort());
Client Connection…
The close() method shuts down both input and output from the socket by
closing the socket.
On occasion, you may want to shut down only half of the connection,
either input or output.
The shutdownInput() and shutdownOutput() methods close only half the
connection:
void shutdownInput()
void shutdownOutput()
Neither actually closes the socket.
Instead, they adjust the stream connected to the socket so that it thinks it’s
at the end of the stream.
Further reads from the input stream after shutting down input return –1.
Further writes to the socket after shutting down output throw an
IOException.
Client Connection…
Reading from and Writing to Sockets
After the server accepts the connection and Socket is created, communication
sockets.
To get an input stream, use the getInputStream() method on a socket object.
object.
For example, the following statements create an InputStream stream and an
Typically, a server runs continuously on a server computer, and clients from all
outputToClient.writeDouble(area);
jta.append("Radius received from client: " + radius + '\n');
jta.append("Area computed: " + area + '\n');
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
2.2 UDP Datagrams
Some applications that you write to communicate over the network will not
require the reliable, point-to-point channel provided by TCP.
Rather, your applications might benefit from a mode of communication that
delivers independent packages of information whose arrival and order of
arrival are not guaranteed.
The UDP protocol provides a mode of network communication whereby
applications send packets of data, called datagrams, to one another.
Datagrams are bundles of information passed between machines.
A datagram is an independent, self-contained message sent over the
network whose arrival, arrival time, and content are not guaranteed.
Once the datagram has been released to its intended target, there is no
assurance that it will arrive at the destination.
Likewise, when the datagram is received, there is no assurance that it
hasn’t been damaged in transit or that whoever sent it is still there to
receive a response.
UDP Datagrams…
UDP is appropriate for data transfers where it doesn't matter if a packet is
lost in transition.
For instance, imagine a transfer of a live TV-signal over the internet.
You want the signal to arrive at the clients as close to live as possible.
Therefore, if a frame or two are lost, you don't really care.
You don't want the live broadcast to be delayed just to make sure all frames
are shown at the client.
You'd rather skip the missed frames, and move directly to the newest
frames at all times.
Java implements datagrams on top of the UDP protocol by using two
classes:
the DatagramPacket which is the data container
DatagramPacket.
UDP Datagrams…
A. DatagramSocket
A DatagramSocket sends as well as receives UDP datagrams.
To send data, you put the data in a DatagramPacket and send the packet
using a DatagramSocket.
To receive data, you take a DatagramPacket object from a DatagramSocket
and then inspect the contents of the packet.
The DatagramSocket themselves are very simple creatures.
In UDP, everything about a datagram, including the address to which it is
directed, is included in the packet itself.
The socket only needs to know the local port on which to listen or send.
DatagramSocket defines four public constructors.
DatagramSocket() – this creates a DatagramSocket bound to
The only difference is the port they bind to: the server socket should bind
By specifying port 0 you ask Java to pick a random available port for you,
method.
This tells the socket to time out after 10 seconds of non-responsiveness:
socket.setSoTimeout(10000);
Timeouts are even more important for UDP than TCP because many
receive data and the size of a packet. It is used for receiving data over a
DatagramSocket.
DatagramPacket(byte data [], int offset, int size) - the second form allows
2.2 UDP Datagrams…
For sending packets, you can create DatagramPacket using the following
constructors:
DatagramPacket(byte data [], int length, InetAddress ip, int port) - this
specifies a target address and port, which are used by a DatagramSocket
to determine where the data in the packet will be sent.
DatagramPacket(byte data [], int offset, int length, InetAddress ip, int
port) – same as the above method except this transmits packets beginning
at the specified offset into the data.
DatagramPacket(byte[] data, int length, SocketAddress destination) –
creates a datagram packet for sending packets of the given length to the
computer specified by SocketAddress.
DatagramPacket(byte[] data, int offset, int length, SocketAddress
destination) – creates a datagram packet for sending packets of the given
length starting from the given offset. The data is sent to the specified port
number and the machine specified with the given SocketAddress.
DatagramPacket Methods
Method Description
Returns the address of the source (for datagrams being received) or
InetAddress getAddress( )
destination (for datagrams being sent).
Returns the byte array of data contained in the datagram. Mostly used
byte[] getData( )
to retrieve data from the datagram after it has been received.
Returns the length of the valid data contained in the byte array that
int getLength( ) would be returned from the getData() method. This may not equal the
length of the whole byte array.
int getOffset( ) Returns the starting index of the data.
The method returns an integer specifying the remote port. If this
datagram was received from the Internet, this is the port on the host
int getPort( ) that sent the packet. If the datagram was created locally to be sent to a
remote host, this is the port to which the packet is addressed on the
remote machine.
void setPort(int port) This method sets the port a datagram is addressed to.
Sets the address to which a packet will be sent. The address is specified
setAddress(InetAddress ip)
by InetAddress.
Sets the data to data, the offset to zero, and the length to number of
void setData(byte[ ] data)
bytes in data.
setData(byte[ ] data, int idx,
Sets the data to data, the offset to idx, and the length to size.
int size)
void setLength(int size) Sets the length of the packet to size.
Example: UDP server that sends hello message to all clients
DatagramSocket sock = null;
Scanner sc = new Scanner(System.in);
try {
sock = new DatagramSocket(7777);
//buffer to receive incoming data
byte[] buffer = new byte[8192];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
System.out.println("Server socket created. Waiting for incoming data...");
//communication loop
while (true) {
sock.receive(incoming);
byte[] data = incoming.getData();
String str = new String(data, 0, incoming.length, “”);
System.out.println("Client: " + str);
System.out.print("Server: ");
String msg = sc.nextLine();
DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.getBytes().length,
incoming.getAddress(), incoming.getPort());
sock.send(dp);
}
} catch (IOException e) {
System.err.println("IOException " + e);
}
Example: UDP client that can connect to the above UDP server
DatagramSocket sock = null;
String str;
Scanner sc = new Scanner(System.in);
try {
sock = new DatagramSocket();
InetAddress host = InetAddress.getByName("localhost");
int port = 7777;
while (true) {
System.out.print("Client: ");
str = sc.nextLine();
byte[] b = str.getBytes();
DatagramPacket dp = new DatagramPacket(b, b.length, host, port);
sock.send(dp);
//now receive reply
byte[] buffer = new byte[8192];
DatagramPacket reply = new DatagramPacket(buffer, buffer.length);
sock.receive(reply);
byte[] data = reply.getData();
String msg = new String(data, 0, reply.length);
System.out.println("Server: " + msg);
}
} catch (IOException e) { System.err.println("IOException " + e); }
REMOTE METHOD
INVOCATION
What is RMI?
The Remote Method Invocation (RMI) system allows an object running in one
machine to invoke methods on an object running in another machine.
RMI provides remote communication between programs written in the Java
programming language.
RMI applications often comprise two separate programs: a server and a client.
A server program creates remote objects, makes references to these objects
accessible, and waits for clients to invoke methods on these objects.
A client program obtains a remote reference to one or more remote objects on
a server and then invokes methods on them.
RMI provides the mechanism by which the server and the client communicate
and pass information back and forth.
Such an application is sometimes referred to as a distributed object application.
A remote object is an object whose methods can be invoked from another JVM
that may be running on a different host.
The object is described by remote interfaces that declare available methods.
What is RMI...
RMI is designed in order to support the distributed object model.
The system architecture consists of three basic layers: the stub/skeleton
layer, remote reference layer, and transport.
A specific interface and protocol defines the boundary at each layer.
Thus, each layer is independent of the next and can be replaced by an
alternate implementation without affecting the other layers in the system.
For example, the current transport implementation is TCP based (using
Java sockets), but a transport based on UDP could be used
interchangeably.
marshaling the return value of the call onto the marshal stream
sequences
deserialization: decoding of a byte sequence and building of a copy of the
RRL manages remote references, parameters and stream-oriented
connection abstraction.
The remote reference layer is responsible for carrying out the semantics of
the type of invocation.
For example this layer is responsible for handling unicast or multicast
invocation to a server.
Each remote object implementation chooses its own invocation semantics —
whether communication to the server is unicast, or the server is part of a
multicast group.
The transport is responsible for connection set-up with remote locations
and connection management, and also keeping track of and dispatching to
remote objects residing in the transport’s local address space.
The transport layer sets up the connections to remote address spaces,
manages them, monitors the connection liveliness, and listens the incoming
calls.
In order to dispatch to a remote object, the server’s transport forwards the
remote call up to the remote reference layer (specific to the server).
The remote reference layer handles any server-side behavior that needs to be
done before handing off the request to the server-side skeleton.
The skeleton for a remote object makes an up-call to the remote object
What is RMI...
RMI communicates as follows:
1. The client obtains a stub instance
2. The client calls the desired methods on the stub and waits for result
3. The stub:
Serializes the information needed for the method invocation (method id
and arguments)
Sends information to the skeleton exploiting the RRL abstractions
4. The skeleton:
Deserializes the received data
Calls the method on the object that implements the server (dispatching)
5. The stub:
Deserializes the return value
RMI treats a remote object differently from a non-remote object when the
object is passed from one JVM to another JVM.
Rather than making a copy of the implementation object in the receiving JVM,
RMI passes a remote stub for a remote object.
The stub acts as the local representative, or proxy, for the remote object and
basically is, to the client, the remote reference.
The client invokes a method on the local stub, which is responsible for
carrying out the method invocation on the remote object.
A stub for a remote object implements the same set of remote interfaces that
the remote object implements.
This property enables a stub to be cast to any of the interfaces that the remote
object implements.
However, only those methods defined in a remote interface are available to be
Designing and Implementing the Application Components
First, determine your application architecture, including which components
are local objects and which components are remotely accessible. This step
includes:
Defining the remote interfaces:
A remote interface specifies the methods that can be invoked remotely by a client.
Clients program to remote interfaces, not to the implementation classes of those
interfaces.
The design of such interfaces includes the determination of the types of objects that
will be used as the parameters and return values for these methods.
If any of these interfaces or classes do not yet exist, you need to define them as well.
Implementing the remote objects:
Remote objects must implement one or more remote interfaces.
The remote object class may include implementations of other interfaces and
methods that are available only locally.
If any local classes are to be used for parameters or return values of any of these
methods, they must be implemented as well.
Implementing the clients:
Clients that use remote objects can be implemented at any time after the remote
interfaces are defined, including after the remote objects have been deployed.
Remote Server
The server code consists of a remote interface and a class that
implements the remote interface.
The interface defines the methods that can be invoked from the
client.
Essentially, the interface defines the client's view of the remote
object.
The class provides the implementation by implementing the
interface.
Remote Server…
A. Remote Interface
A remote interface extends the interface java.rmi.Remote
java.rmi.RemoteException.
This exception is thrown by the RMI system from a remote method invocation
Remote method calls initiated by the client are actually directed to the stub.
It works with the other parts of the RMI system to receive requests,
To generate stubs and skeletons, you use a tool called the RMI compiler,
void bind(String name, Binds a remote reference to the specified name in this registry. It
Remote obj) throws RemoteException, AlreadyBoundException, AccessException.
Replaces the binding for the specified name in this registry with the
void rebind(String name, supplied remote reference. If there is an existing binding for the
Remote obj) specified name, it is discarded. It throws RemoteException,
AccessException.
void unbind(String name) Removes the binding for the specified name in this registry. It
throws RemoteException, NotBoundException, AccessException
Remote lookup(String It returns the remote reference bound to the specified name in this
name) registry. It throws RemoteException, NotBoundException,
AccessException.
Returns an array of the names bound in this registry. The array will
String[] list() contain a snapshot of the names bound in this registry. It throws
RemoteException, AccessException.
RMI Registry
Note the following about the Registry.rebind invocation:
The no-argument version of LocateRegistry.getRegistry synthesizes a
reference to a registry on the localhost & on the default registry port, 1099.
You must use an overload that has an int parameter if the registry is
created on a port other than 1099.
When a remote invocation on the registry is made, a stub for the remote
object is passed instead of a copy of the remote object itself. Remote
implementation objects, such as instances of AddServer, never leave the
JVM in which they were created. Thus, when a client performs a lookup in
a server's remote object registry, a copy of the stub is returned. Remote
objects in such cases are thus effectively passed by reference rather than
by value.
For security reasons, an application can only bind, unbind, or rebind
remote object references with a registry running on the same host. This
restriction prevents a remote client from removing or overwriting any of
the entries in a server's registry. A lookup, however, can be requested from
any host, local or remote.
RMI Registry
The Naming class provides methods for storing and obtaining
references to remote objects in a remote object registry.
Each method of the Naming class takes as one of its arguments a
name that is a String in URL format of the form:
rmi://host:port/name
Before clients can lookup remote objects on RMI registry, the
registry first should be started.
To start the RMI Registry from the command line, use the following
command:
start rmiregistry
RMI Registry…
Methods of Naming class
Method description
It returns a reference, a stub, for the remote object
associated with the specified name. The method throws
static Remote lookup(String name) NotBoundException, MalformedURLException, and
RemoteException.
It binds the remote object with the given name. It throws
static void bind(String name, Remote r) AlreadyBoundException, MalformedURLException, and
RemoteException.
It destroys the remote object which is bound with the given
static void unbind(String name) name. It throws RemoteException, NotBoundException, and
MalformedURLException.
It rebinds the specified name to a new remote object. Any
static void rebind(String name, Remote r) existing binding for the name is replaced. It throws
RemoteException, and MalformedURLException.
It returns an array of the names of the remote objects bound
static String[] list(String name) to the registry. The name parameter is a registry name in URL
format. It throws RemoteException, and
MalformedURLException.
RMI Registry…
What is the difference between Naming and registry?
The difference is that the name arguments you pass to java.rmi.Naming are
in URL format, and include the location of the registry, whereas with
java.rmi.registry.Registry, the name is just the name.
Also, the methods on Naming are static.
For example, you would call something like this:
Naming.rebind("//host/objName", myObj);
Whereas with Registry, you need an existing handle on the registry object,
and you'd call:
Registry registry =LocateRegistry.getRegistry();
registry.rebind("objName", myObj);
Generally, Naming is really just a convenience class that saves you having
to look up the Registry manually because it performs the registry lookup
and rebind in one step.
RMI Client
The client class does not have to do much to access the RMI
server.
The only thing the client should do is get reference of remote
object in order to call its methods.
This is done using the Naming class.
Once the client gets reference of remote object, it can call the
remote methods.
Example: RMI that accepts two numbers, add them and display the result on client
//remote interface
public interface AddInterface extends Remote{
Server side
double add(double d1, double d2) throws RemoteException;
}
//remote object
public class AddServer extends UnicastRemoteObject implements AddInterface {
public AddServer() throws RemoteException { }
public double add(double d1, double d2) throws RemoteException {
return d1 + d2;
}
public static void main(String args[]) {
try {
AddServer addServer = new AddServer ();
Naming.bind("AddServerObject", addServer);
System.out.println("Server started...");
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}}
//remote interface
public interface AddInterface extends Remote{
double add(double d1, double d2) throws RemoteException;
} Client side
//client
public class AddClient {
public static void main(String args[]) {
try {
String addServerURL = "rmi://localhost/AddServerObject";
AddInterface addServerIntf = (AddInterface) Naming.lookup(addServerURL);