[go: up one dir, main page]

0% found this document useful (0 votes)
2 views41 pages

Java Networking

The document provides an overview of Java networking, specifically focusing on socket programming using TCP and UDP protocols. It explains the roles of the java.net package, detailing the ServerSocket and Socket classes, their methods, and how to implement client-server communication. Additionally, it includes example code for both TCP and UDP client-server applications, demonstrating message passing and non-Fibonacci number calculations.

Uploaded by

yopm34347
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views41 pages

Java Networking

The document provides an overview of Java networking, specifically focusing on socket programming using TCP and UDP protocols. It explains the roles of the java.net package, detailing the ServerSocket and Socket classes, their methods, and how to implement client-server communication. Additionally, it includes example code for both TCP and UDP client-server applications, demonstrating message passing and non-Fibonacci number calculations.

Uploaded by

yopm34347
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 41

Java - Networking (Socket Programming)

The term network programming refers to writing programs that execute across multiple devices
(computers),in which the devices are all connected to each other using a network. The java.net
package of the J2SE APIs contains a collection of classes and interfaces that provide the low-
level communication details, allowing you to write programs that focus on solving the problem
at hand. The java.net package provides support for the two common network protocols:

TCP: TCP stands for Transmission Control Protocol, which allows for reliable communication
between two applications. TCP is typically used over the Internet Protocol, which is referred to
as TCP/IP.

UDP: UDP stands for User Datagram Protocol, a connection-less protocol that allows for
packets of data to be transmitted between applications.

Socket Programming: This is most widely used concept in Networking and it has been
explained in very detail.

Socket Programming :
Sockets provide the communication mechanism between two computers using TCP. A client
program creates a socket on its end of the communication and attempts to connect that socket to
a server. When the connection is made, the server creates a socket object on its end of the
communication. The client and server can now communicate by writing to and reading from the
socket. The java.net.Socket class represents a socket, and the java.net.ServerSocket class
provides a mechanism for the server program to listen for clients and establish connections with
them.
The following steps occur when establishing a TCP connection between two computers using
sockets: The server instantiates a ServerSocket object, denoting which port number
communication is to occur on. The server invokes the accept() method of the ServerSocket class.
T his method waits until a client connects to the server on the given port.
After the server is waiting, a client instantiates a Socket object, specifying the server name and
port number to connect to. The constructor of the Socket class attempts to connect the client to
the specified server and port number. If communication is established, the client now has a
Socket object capable of communicating with the server. On the server side, the accept() method
returns a reference to a new socket on the server that is connected to the client's socket. After the
connections are established, communication can occur using I/O streams. Each socket has both
an OutputStream and an InputStream. The client's OutputStream is connected to the server's
InputStream, and the client's InputStream is connected to the server's OutputStream.
TCP is a two way communication protocol, so data can be sent across both streams at the same
time. There are following useful classes providing complete set of methods to implement
sockets.

ServerSocket Class Methods:


The java.net.ServerSocket class is used by server applications to obtain a port and listen for
client requests. The ServerSocket class has four constructors:

Methods with Description

1. public ServerSocket(int port) throws IO Exception


Attempts to create a server socket bound to the specified port. An exception occurs if the port is
already bound by another application

2. public ServerSocket(int port, int backlog ) throws IO Exception


Similar to the previous constructor, the backlog parameter specifies how many incoming clients
to store in a wait queue.

3. public ServerSocket(int port, int backlog , InetAddress address) throws IO


Exception
Similar to the previous constructor, the InetAddress parameter specifies the local IP address to
bind to. T he InetAddress is used for servers that may have multiple IP addresses, allowing the
server to specify which of its IP addresses to accept client requests on.

4. public ServerSocket() throws IO Exception


Creates an unbound server socket. When using this constructor, use the bind() method when you
are ready to bind the server socket If the ServerSocket constructor does not throw an exception,
it means that your application has successfully bound to the specified port and is ready for client
requests.
Here are some of the common methods of the ServerSocket class:

Methods with Description


1. public int getLocalPort()
Returns the port that the server socket is listening on. This method is useful if you passed in 0 as
the port number in a constructor and let the server find a port for you.

2. public Socket accept() throws IO Exception


Waits for an incoming client. T his method blocks until either a client connects to the server on
the specified port or the socket times out, assuming that the time-out value has been set using the
setSoTimeout() method. Otherwise, this method blocks indefinitely

3. public void setSoTimeout(int timeout)


Sets the time-out value for how long the server socket waits for a client during the accept().

4. public void bind(Socket Address host, int backlog )


Binds the socket to the specified server and port in the SocketAddress object. Use this method if
you instantiated the ServerSocket using the no-argument constructor. When the ServerSocket
invokes accept(), the method does not return until a client connects. After a client does connect,
the ServerSocket creates a new Socket on an unspecified port and returns a reference to this new
Socket. A TCP connection now exists between the client and server, and communication can
begin.
Socket Class Methods:
The java.net.Socket class represents the socket that both the client and server use to
communicate with each other. The client obtains a Socket object by instantiating one, whereas
the server obtains a Socket object from the return value of the accept() method.
The Socket class has five 8constructors that a client uses to connect to a server:
Methods with Description
1. public Socket(String host, int port) throws UnknownHostException, IO Exception.
T his method attempts to connect to the specified server at the specified port. If this constructor
does not throw an exception, the connection is successful and the client is connected to the
server.

2. public Socket(InetAddress host, int port) throws IO Exception


T his method is identical to the previous constructor, except that the host is denoted by an
InetAddress object.

3. public Socket(String host, int port, InetAddress localAddress, int localPort) throws
IO Exception.
Connects to the specified host and port, creating a socket on the local host at the specified
address and port.

4. public Socket(InetAddress host, int port, InetAddress localAddress, int localPort)


throws IO Exception.
T his method is identical to the previous constructor, except that the host is denoted by an
InetAddress object instead of a String.

5. public Socket()
Creates an unconnected socket. Use the connect() method to connect this socket to a server.
When the Socket constructor returns, it does not simply instantiate a Socket object but it actually
attempts to connect to the specified server and port. Some methods of interest in the Socket class
are listed here. Notice that both the client and server have a Socket object, so these methods can
be invoked by both the client and server.

Methods with Description


1. public void connect(Socket Address host, int timeout) throws IO Exception
T his method connects the socket to the specified host. T his method is needed only when you
instantiated the Socket using the no-arg ument constructor.

2. public InetAddress getInetAddress()


T his method returns the address of the other computer that this socket is connected to.

3. public int getPort()


Returns the port the socket is bound to on the remote machine.

4. public int getLocalPort()


Returns the port the socket is bound to on the local machine.

5. public SocketAddress getRemoteSocketAddress()


Returns the address of the remote socket.

6. public InputStream getInputStream() throws IO Exception


Returns the input stream of the socket. T he input stream is connected to the output stream of the
remote socket.

7. public OutputStream getOutputStream() throws IO Exception


Returns the output stream of the socket. T he output stream is connected to the input stream of
the remote socket.

8. public void close() throws IO Exception


Closes the socket, which makes this Socket object no longer capable of connecting again to any
server.
InetAddress Class Methods:
T his class represents an Internet Protocol (IP) address. Here are following useful methods which
you would need while doing socket programming.

Methods with Desc ription


1. static InetAddress getByAddress(byte[] addr)
Returns an InetAddress object g iven the raw IP address .

2. static InetAddress getByAddress(String host, byte[] addr)


Create an InetAddress based on the provided host name and IP address.

3. static InetAddress getByName(String host)


Determines the IP address of a host, given the host's name.

4. String getHostAddress()
Returns the IP address string in textual presentation.

5. String g etHostName()
Gets the host name for this IP address.

6. static InetAddress InetAddress g etLoc alHost()


Returns the local host.

7. String toString ()
Converts this IP address to a String .

1. Implementation of a client server Programming using UDP for simple


message passing
Algorithm:

1. Create a server client communication using UDP.

2. Server wait for client to start.

3. Client communicated to the server after connection is formed.

4. Server greets the client connected.


Client:
The following Greeting Client is a client program that connects to a server by using a socket and
sends a greeting, and then waits for a response.

// File Name GreetingClient.java


import java.net.*;
import java.io.*;
public class GreetingClient
{
public static void main(String [] args)
{
String serverName = args[0];
int port = Integer.parseInt(args[1]);
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.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{ e.printStackTrace();
}
}
}
Server:
The following Greeting Server program is an example of a server application that uses the
Socket class to listen for clients on a port number specified by a command-line argument:

// File Name GreetingServer.java


import java.net.*;
import java.io.*;
public class GreetingServer extends Thread
{
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run()
{
while(true)
{
try
{
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to "+ server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to "+ server.getLocalSocketAddress() + \
nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}

public static void main(String [] args)


{
int port = Integer.parseInt(args[0]);
try
{
Thread t = new GreetingServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}

Input/Output :
Compile client and server and then start server as follows:
$ java GreetingServer 6066
Waiting for client on port 6066...
Check client prog ram as follows:

$ java GreetingClient localhost 6066


Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!

2. Write a program to display a list of Non-Fibonacci numbers using UDP in


client server architecture.
Algorithm:

1. Create a server client communication using UDP.

2. Implement a method to compute the Non Fibonacci numbers at the server side.

3. Give the required input from the client.

4. Server computes the results and sends it to the client.

Server Program:

import java.net.*;
import java.io.*;
public class UDPServerNonFibo{
public static String non_fibonacci(int num)
{
int i,temp,fib1 = 3,fib2 = 5;
String non_fib,num_txt;
non_fib = "0";
while(fib1<=num)
{
for(i=fib1+1;i<fib2;i++)
{
if(i<=num)
{
num_txt = Integer.toString(i);
num_txt = ","+num_txt;
non_fib = non_fib + num_txt;
}
}
temp=fib1;
fib1=fib2;
fib2=temp+fib2;
}
return non_fib;
}
public static void main(String args[]){
DatagramSocket aSocket = null;
int port = Integer.parseInt(args[0]);
try
{
aSocket = new DatagramSocket(port);
byte[] buffer = new byte[1000];
byte[] m = new byte[1000];
int n;
String answer;
while(true)
{
DatagramPacket request = new DatagramPacket(buffer, buffer.length);
aSocket.receive(request);
String received_text = new String( request.getData());
n = Integer.parseInt(received_text.trim());
answer = non_fibonacci(n);
m = answer.getBytes();
DatagramPacket reply = new DatagramPacket(m,m.length,
request.getAddress(), request.getPort());
aSocket.send(reply);
System.out.println("Non-fibonacci series upto "+n+" is:
"+answer);
}
}
catch (SocketException e)
{
System.out.println("Socket: " + e.getMessage());
}
catch (IOException e)
{
System.out.println("IO: " + e.getMessage());
}
finally
{
if(aSocket != null) aSocket.close();
}
}
}

Client Program:

import java.net.*;
import java.io.*;
public class UDPClientNonFibo{
public static void main(String args[]){
DatagramSocket aSocket = null;
try
{
aSocket = new DatagramSocket();
byte [] m = args[0].getBytes();
InetAddress aHost = InetAddress.getByName(args[1]);
int serverPort = Integer.parseInt(args[2]);
DatagramPacket request = new DatagramPacket(m, m.length, aHost,
serverPort);
aSocket.send(request);
byte[] buffer = new byte[1000];
DatagramPacket reply = new DatagramPacket(buffer, buffer.length);
aSocket.receive(reply);
System.out.println("Non-fibonacci: " + new String(reply.getData()));
}
catch (SocketException e)
{
System.out.println("Socket: " + e.getMessage());
}
catch (IOException e)
{
System.out.println("IO: " + e.getMessage());
}
finally
{
if(aSocket != null) aSocket.close();
}
}
}

Input : 3 (no of Non Fibonacci Numbers)

Output : Non-fibonacci series upto 3 is: 4 6 7


3. Implementation of a client server Programming using TCP for simple
message passing
Algorithm:

1. Create a server client communication using TCP.

2. Take input from the keyboard in the client side.

3. Send the message from the client to the server.

4. Server converts the message in its upper case and sends it to the client.

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

class TCPServer {
public static void main(String argv[]) throws Exception {
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);

while (true) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new
DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println("Received: " + clientSentence);
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
}
}
}

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

class TCPClient {
public static void main(String argv[]) throws Exception {
String sentence;
String modifiedSentence;
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("localhost", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new
InputStreamReader(clientSocket.getInputStream()));
sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence);
clientSocket.close();
}
}

Input/Output:

1. Client : hello
2. Server :
Received : hello
3. Client : HELLO

4. Write a program to implement Factorial of a number using TCP in client


server architecture.
Algorithm:

1. Create a server client communication using TCP.

2. Implement a method to compute the factorial of a number at the server side.

3. Give the required input from the client.

4. Server computes the results and sends it to the client.

Client :
import java.io.*;
import java.net.*;
class FactorialClient
{
public static void main(String arg[])
{
int port=9999;
Socket s;
String msg="";
try
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
InetAddress addr=InetAddress.getByName(null);
s=new Socket(addr,port);
OutputStreamWriter osw=new OutputStreamWriter(s.getOutputStream());
PrintWriter pw=new PrintWriter(osw);
BufferedReader br1=new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.print("Enter a Number : ");
String str=br.readLine();

pw.println(str);
pw.flush();
msg=br1.readLine();
System.out.println("Answer from server : ");
System.out.println(msg);
}
catch(Exception e)
{
// Ignore
}
}
}

Server:
import java.io.*;
import java.net.*;

class FactorialServer implements Runnable


{
Socket s;
int id;
public static void main(String arg[])
{
int port=9999,count=0;
try
{
// create new socket
ServerSocket ss=new ServerSocket(port);
System.out.println("Waiting for client");
while(true)
{
Socket s=ss.accept();
FactorialServer serve=new FactorialServer(s,count);
// launch new thread
Thread t=new Thread(serve);
t.start();
}
}
catch(Exception e)
{
// Ignore error
System.out.println("Error");
}
}

FactorialServer(Socket s,int id)


{
this.s = s;
this.id = id;
}

public void run()


{
try
{
BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw=new PrintWriter(new OutputStreamWriter(s.getOutputStream())) ;
String str=br.readLine();
int n=Integer.parseInt(str);
int i;
long f=1;
System.out.println("Number sent by client: " + n);
for(i = 2; i <= n; i++)
f = f * i;
pw.println("Factorial is : "+f);
pw.flush();
}
catch(Exception e)
{
// Ignore error
System.out.println("Thread: Error");
}
}
}
Input/Output:

1. Client :
Enter a number : 4
2. Server:
Number sent by client : 4
3. Client :
Answer from Server
Factorial is : 12

5. Write a program to implement Factorial of a number using client server


architecture. The program serves more than one client at a time.

Algorithm:

1. Create a server client communication using TCP.

2. Implement a method to compute the factorial of a number at the server side.

3. Give the required input from the client.

4. Server computes the results and sends it to the client.

Server Program:

import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
public class MultiThreadFactorialServer {

// The server socket.


private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;

// This program can accept up to maxClientsCount clients' connections.


private static final int maxClientsCount = 10;
private static final clientThread[] threads = new clientThread[maxClientsCount];
public static void main(String args[]) {
int portNumber = 7000;
if (args.length < 1) {
System.out.println("Usage: java MultiThreadFactrialServer <portNumber>\n"
+ "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
try {
serverSocket = new ServerSocket(portNumber);
} catch (IOException e) {
System.out.println(e);
}

/*
* Create a client socket for each connection and pass it to a new client
* thread.
*/
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket,threads)).start();
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}

class clientThread extends Thread {

private DataInputStream is = null;


private PrintStream os = null;
private Socket clientSocket = null;
private final clientThread[] threads;
private int maxClientsCount;

public clientThread(Socket clientSocket, clientThread[] threads) {


this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
}
//funcation that returns factorial of a number
public static int factorial(int n)
{
int fact;
if(n==0)
fact = 1;
else
fact = n*factorial(n-1);
return fact;
}
public void run() {
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;

try {
/*
* Create input and output streams for this client.
*/
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
//os.println("Enter the number.");
String num = is.readLine().trim();
Integer n = Integer.parseInt(num);
int fact = factorial(n);
String answer = Integer.toString(fact);
for (int i = 0; i < maxClientsCount; i++) {

if (threads[i] != null && threads[i] == this)


{
threads[i].os.println("Factorial is: "+fact);
}
}
is.close();
os.close();
clientSocket.close();
} catch (IOException e) {
}
}
}

Client Program:

import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class MultiThreadFactorialClient implements Runnable {

// The client socket


private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static DataInputStream is = null;

private static BufferedReader inputLine = null;


private static boolean closed = false;

public static void main(String[] args) {

// The default port.


int portNumber = 6679;
// The default host.
String host = "localhost";

if (args.length < 2) {
System.out
.println("Usage: java MultiThreadChatClient <host> <portNumber>\n"
+ "Now using host=" + host + ", portNumber=" + portNumber);
} else {
host = args[0];
portNumber = Integer.valueOf(args[1]).intValue();
}

/*
* Open a socket on a given host and port. Open input and output streams.
*/
try {
clientSocket = new Socket(host, portNumber);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
is = new DataInputStream(clientSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + host);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host "
+ host);
}
if (clientSocket != null && os != null && is != null) {
try {

/* Create a thread to read from the server. */


new Thread(new MultiThreadFactorialClient()).start();
while (!closed) {
os.println(inputLine.readLine().trim());
}
/*
* Close the output stream, close the input stream, close the socket.
*/
os.close();
is.close();
clientSocket.close();
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}

public void run() {


String responseLine;
try {
System.out.println("Please enter the number");
while ((responseLine = is.readLine()) != null) {
System.out.println(responseLine);
}
closed = true;
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}

Input : Enter the number : 4


Output : The factorial is : 24.

6. Write a program to implement a File Server in client server architecture.


Algorithm:

1. Create a server client communication using UDP.

2. Give the required input from the client.

3. Implement a method to read the contents of a file at the server side.

4. Server computes the results and sends it to the client.

Server Program:

import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
public class FileServer {

// The server socket.


private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;

// This program can accept up to maxClientsCount clients' connections.


private static final int maxClientsCount = 10;
private static final clientThread[] threads = new clientThread[maxClientsCount];

public static void main(String args[]) {


int portNumber = 7000;
if (args.length < 1) {
System.out
.println("Usage: java FileServer <portNumber>\n"
+ "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
try {
serverSocket = new ServerSocket(portNumber);
} catch (IOException e) {
System.out.println(e);
}

/*
* Create a client socket for each connection and pass it to a new client
* thread.
*/
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}

class clientThread extends Thread {

private DataInputStream is = null;


private PrintStream os = null;
private Socket clientSocket = null;
private final clientThread[] threads;
private int maxClientsCount;

public clientThread(Socket clientSocket, clientThread[] threads) {


this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
}
public void run() {
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;

try {
/*
* Create input and output streams for this client.
*/
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
//os.println("Enter the number.");
String file = is.readLine().trim();
System.out.println(file);
for (int i = 0; i < maxClientsCount; i++) {

if (threads[i] != null && threads[i] == this)


{
threads[i].os.println("Filename is: "+file);
}
}
is.close();
os.close();
clientSocket.close();
} catch (IOException e) {
}
}
}

Client Program:

import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class FileClient{

// The client socket


private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static DataInputStream is = null;
private static BufferedReader inputLine = null;
private static boolean closed = false;

public static void main(String[] args) {

// The default port.


int portNumber = 7000;
// The default host.
String host = "localhost";

if (args.length < 2) {
System.out
.println("Usage: java MultiThreadChatClient <host> <portNumber>\n"
+ "Now using host=" + host + ", portNumber=" + portNumber);
} else {
host = args[0];
portNumber = Integer.valueOf(args[1]).intValue();
}

/*
* Open a socket on a given host and port. Open input and output streams.
*/
try {
clientSocket = new Socket(host, portNumber);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
is = new DataInputStream(clientSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + host);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host "
+ host);
}
if (clientSocket != null && os != null && is != null) {

/* Create a thread to read from the server. */


try{
String responseLine;
System.out.println("1: Send file.");
System.out.println("2: Recieve file.");
System.out.println("Please make selection");
Scanner input = new Scanner(System.in);
int option = input.nextInt();
switch(option)
{
case 1:
System.out.println("Enter fielname to send");
String file = inputLine.readLine().trim();
os.println(file);
break;
case 2:
file = inputLine.readLine().trim();
os.println(file);
break;
}
}
catch (IOException e)
{
System.out.println(e);
}
}
try{
os.println(inputLine.readLine().trim());
/*
* Close the output stream, close the input stream, close the socket.
*/
os.close();
is.close();
clientSocket.close();
}
catch(IOException e)
{
System.out.println(e);
}
}
}

Input: Enter the name of the File : abc.txt


Output : The contents are: Hello World.

Java Remote Method Invocation

Java RMI Tutorial

 Introduction
 Serializable Classes
 Remote Classes and Interfaces
 Programming a Client
 Programming a Server
 Starting the Server
 Running a Client
 Security

Introduction

This is a brief introduction to Java Remote Method Invocation (RMI). Java RMI is a mechanism
that allows one to invoke a method on an object that exists in another address space. The other
address space could be on the same machine or a different one. The RMI mechanism is basically
an object-oriented RPC mechanism. CORBA is another object-oriented RPC mechanism.
CORBA differs from Java RMI in a number of ways:

1. CORBA is a language-independent standard.


2. CORBA includes many other mechanisms in its standard (such as a standard for TP
monitors) none of which are part of Java RMI.
3. There is also no notion of an "object request broker" in Java RMI.

Java RMI has recently been evolving toward becoming more compatible with CORBA. In
particular, there is now a form of RMI called RMI/IIOP ("RMI over IIOP") that uses the Internet
Inter-ORB Protocol (IIOP) of CORBA as the underlying protocol for RMI communication.

This tutorial attempts to show the essence of RMI, without discussing any extraneous features.
Sun has provided a Guide to RMI , but it includes a lot of material that is not relevant to RMI
itself. For example, it discusses how to incorporate RMI into an Applet, how to use packages and
how to place compiled classes in a different directory than the source code. All of these are
interesting in themselves, but they have nothing at all to do with RMI. As a result, Sun's guide is
unnecessarily confusing. Moreover, Sun's guide and examples omit a number of details that are
important for RMI.

There are three processes that participate in supporting remote method invocation.

1. The Client is the process that is invoking a method on a remote object.


2. The Server is the process that owns the remote object. The remote object is an ordinary
object in the address space of the server process.
3. The Object Registry is a name server that relates objects with names. Objects
are registered with the Object Registry. Once an object has been registered, one can use
the Object Registry to obtain access to a remote object using the name of the object.

In this tutorial, we will give an example of a Client and a Server that solve the classical "Hello,
world!" problem. You should try extracting the code that is presented and running it on your own
computer.

There are two kinds of classes that can be used in Java RMI.
1. A Remote class is one whose instances can be used remotely. An object of such a class
can be referenced in two different ways:
1. Within the address space where the object was constructed, the object is an
ordinary object which can be used like any other object.
2. Within other address spaces, the object can be referenced using an object handle.
While there are limitations on how one can use an object handle compared to an
object, for the most part one can use object handles in the same way as an
ordinary object.

For simplicity, an instance of a Remote class will be called a remote object.

2. A Serializable class is one whose instances can be copied from one address space to
another. An instance of a Serializable class will be called a serializable object. In other
words, a serializable object is one that can be marshaled. Note that this concept has no
connection to the concept of serializability in database management systems.

If a serializable object is passed as a parameter (or return value) of a remote method


invocation, then the value of the object will be copied from one address space to the
other. By contrast if a remote object is passed as a parameter (or return value), then the
object handle will be copied from one address space to the other.

One might naturally wonder what would happen if a class were both Remote and Serializable.
While this might be possible in theory, it is a poor design to mix these two notions as it makes
the design difficult to understand.

Serializable Classes

We now consider how to design Remote and Serializable classes. The easier of the two is a
Serializable class. A class is Serializable if it implements the java.io.Serializable interface.
Subclasses of a Serializable class are also Serializable. Many of the standard classes are
Serializable, so a subclass of one of these is automatically also Serializable. Normally, any data
within a Serializable class should also be Serializable. Although there are ways to include non-
serializable objects within a serializable objects, it is awkward to do so. See the documentation
of java.io.Serializable for more information about this.

Using a serializable object in a remote method invocation is straightforward. One simply passes
the object using a parameter or as the return value. The type of the parameter or return value is
the Serializable class. Note that both the Client and Server programs must have access to the
definition of any Serializable class that is being used. If the Client and Server programs are on
different machines, then class definitions of Serializable classes may have to be downloaded
from one machine to the other. Such a download could violate system security. This problem is
discussed in the Security section.

The only Serializable class that will be used in the "Hello, world!" example is the String class, so
no problems with security arise.
Remote Classes and Interfaces

Next consider how to define a Remote class. This is more difficult than defining a Serializable
class. A Remote class has two parts: the interface and the class itself. The Remote interface must
have the following properties:

1. The interface must be public.


2. The interface must extend the interface java.rmi.Remote.
3. Every method in the interface must declare that it throws java.rmi.RemoteException.
Other exceptions may also be thrown.

The Remote class itself has the following properties:

1. It must implement a Remote interface.


2. It should extend the java.rmi.server.UnicastRemoteObject class. Objects of such a class
exist in the address space of the server and can be invoked remotely. While there are
other ways to define a Remote class, this is the simplest way to ensure that objects of a
class can be used as remote objects. See the documentation of the java.rmi.server package
for more information.
3. It can have methods that are not in its Remote interface. These can only be invoked
locally.

Unlike the case of a Serializable class, it is not necessary for both the Client and the Server to
have access to the definition of the Remote class. The Server requires the definition of both the
Remote class and the Remote interface, but the Client only uses the Remote interface. Roughly
speaking, the Remote interface represents the type of an object handle, while the Remote class
represents the type of an object. If a remote object is being used remotely, its type must be
declared to be the type of the Remote interface, not the type of the Remote class.

In the example program, we need a Remote class and its corresponding Remote interface. We
call these Hello and HelloInterface, respectively. Here is the file HelloInterface.java:

import java.rmi.*;
/**
* Remote Interface for the "Hello, world!" example.
*/
public interface HelloInterface extends Remote {
/**
* Remotely invocable method.
* @return the message of the remote object, such as "Hello, world!".
* @exception RemoteException if the remote invocation fails.
*/
public String say() throws RemoteException;
}
Here is the file Hello.java:
import java.rmi.*;
import java.rmi.server.*;
/**
* Remote Class for the "Hello, world!" example.
*/
public class Hello extends UnicastRemoteObject implements HelloInterface {
private String message;
/**
* Construct a remote object
* @param msg the message of the remote object, such as "Hello, world!".
* @exception RemoteException if the object handle cannot be constructed.
*/
public Hello (String msg) throws RemoteException {
message = msg;
}
/**
* Implementation of the remotely invocable method.
* @return the message of the remote object, such as "Hello, world!".
* @exception RemoteException if the remote invocation fails.
*/
public String say() throws RemoteException {
return message;
}
}

All of the Remote interfaces and classes should be compiled using javac. Once this has been
completed, the stubs and skeletons for the Remote interfaces should be compiled by using
the rmic stub compiler. The stub and skeleton of the example Remote interface are compiled
with the command:

rmic Hello

The only problem one might encounter with this command is that rmic might not be able to find
the files Hello.class and HelloInterface.class even though they are in the same directory
where rmic is being executed. If this happens to you, then try setting
the CLASSPATH environment variable to the current directory, as in the following command:

setenv CLASSPATH .
If your CLASSPATH variable already has some directories in it, then you might want to add the
current directory to the others.

Programming a Client

Having described how to define Remote and Serializable classes, we now discuss how to
program the Client and Server. The Client itself is just a Java program. It need not be part of a
Remote or Serializable class, although it will use Remote and Serializable classes.
A remote method invocation can return a remote object as its return value, but one must have a
remote object in order to perform a remote method invocation. So to obtain a remote object one
must already have one. Accordingly, there must be a separate mechanism for obtaining the first
remote object. The Object Registry fulfills this requirement. It allows one to obtain a remote
object using only the name of the remote object.

The name of a remote object includes the following information:

1. The Internet name (or address) of the machine that is running the Object Registry with
which the remote object is being registered. If the Object Registry is running on the same
machine as the one that is making the request, then the name of the machine can be
omitted.
2. The port to which the Object Registry is listening. If the Object Registry is listening to
the default port, 1099, then this does not have to be included in the name.
3. The local name of the remote object within the Object Registry.

Here is the example Client program:


/**
* Client program for the "Hello, world!" example.
* @param argv The command line arguments which are ignored.
*/
public static void main (String[] argv) {
try {
HelloInterface hello =
(HelloInterface) Naming.lookup ("//ortles.ccs.neu.edu/Hello");
System.out.println (hello.say());
} catch (Exception e) {
System.out.println ("HelloClient exception: " + e);
}
}

The Naming.lookup method obtains an object handle from the Object Registry running
on ortles.ccs.neu.edu and listening to the default port. Note that the result
of Naming.lookup must be cast to the type of the Remote interface.

The remote method invocation in the example Client is hello.say(). It returns a String which is
then printed. A remote method invocation can return a String object because String is a
Serializable class.

The code for the Client can be placed in any convenient class. In the example Client, it was
placed in a class HelloClient that contains only the program above.

Programming a Server

The Server itself is just a Java program. It need not be a Remote or Serializable class, although it
will use them. The Server does have some responsibilities:
1. If class definitions for Serializable classes need to be downloaded from another machine,
then the security policy of your program must be modified. Java provides a security
manager class called RMISecurityManager for this purpose. The RMISecurityManager
defines a security policy that allows the downloading of Serializable classes from another
machine. The "Hello, World!" example does not need such downloads, since the only
Serializable class it uses is String. As a result it isn't necessary to modify the security
policy for the example program. If your program defines Serializable classes that need to
be downloaded to another machine, then insert the statement System.setSecurityManager
(new RMISecurityManager()); as the first statement in the main program below. If this
does not work for your program, then you should consult the Security section below.
2. At least one remote object must be registered with the Object Registry. The statement for
this is: Naming.rebind (objectName, object); where object is the remote object being
registered, and objectName is the String that names the remote object.

Here is the example Server:


/**
* Server program for the "Hello, world!" example.
* @param argv The command line arguments which are ignored.
*/
public static void main (String[] argv) {
try {
Naming.rebind ("Hello", new Hello ("Hello, world!"));
System.out.println ("Hello Server is ready.");
} catch (Exception e) {
System.out.println ("Hello Server failed: " + e);
}
}
The rmiregistry Object Registry only accepts requests to bind and unbind objects running on the
same machine, so it is never necessary to specify the name of the machine when one is
registering an object.

The code for the Server can be placed in any convenient class. In the example Server, it was
placed in a class HelloServer that contains only the program above.

Starting the Server

Before starting the Server, one should first start the Object Registry, and leave it running in the
background. One performs this by using the command:

rmiregistry &
It takes a second or so for the Object Registry to start running and to start listening on its socket.
If one is using a script, then one should program a pause after starting the Object Registry. If one
is typing at the command line, it is unlikely that one could type fast enough to get ahead of the
Object Registry.
The Server should then be started; and, like the Object Registry, left running in the background.
The example Server is started using the command:

java HelloServer &


The Server will take a few seconds to start running, and to construct and register remote objects.
So one should wait a few seconds before running any Clients. Printing a suitable message, as in
the example Server, is helpful for determining when the Server is ready.

Running a Client

Th Client is run like any other java program. The example Client is executed using:

java HelloClient

Security

One of the most common problems one encounters with RMI is a failure due to security
constraints. This section gives a very brief introduction to the Java security model as it relates to
RMI. For a more complete treatment, one should read the documentation for the Java
SecurityManager and Policy classes and their related classes. Note that this section assumes that
one is using Java 1.2 or later. Some of the statements are not true for earlier versions.

A Java program may specify a security manager that determines its security policy. A program
will not have any security manager unless one is specified. One sets the security policy by
constructing a SecurityManager object and calling the setSecurityManager method of the System
class. Certain operations require that there be a security manager. For example, RMI will
download a Serializable class from another machine only if there is a security manager and the
security manager permits the downloading of the class from that machine. The
RMISecurityManager class defines an example of a security manager that normally permits such
downloads.

However, many Java installations have instituted security policies that are more restrictive than
the default. There are good reasons for instituting such policies, and one should not override
them carelessly. The rest of this section discusses some ways that can be used for overriding
security policies that prevent RMI from functioning properly.

The SecurityManager class has a large number of methods whose name begins with check. For
example, checkConnect (String host, int port). If a check method returns, then the permission
was granted. For example, if a call to checkConnect returns normally, then the current security
policy allows the program to establish a socket connection to the server socket at the specified
host and port. If the current security policy does not allow one to connect to this host and port,
then the call throws an exception. This usually causes your program to terminate with a message
such as:

java.security.AccessControlException: access denied


(java.net.SocketPermission 127.0.0.1:1099 connect,resolve)
The message above would occur when an RMI server or client was not allowed to connect to the
RMI registry running on the same machine as the server or client.

As discussed above, one sets the security policy by passing an object of type SecurityManager to
the setSecurityManager method of the System class. There are several ways to modify the
security policy of a program. The simplest technique is to define a subclass of SecurityManager
and to callSystem.setSecurityManager on an object of this subclass. In the definition of this
subclass, you should override those check methods for which you want a different policy. For
example, if you find that your "Hello, World!" program refuses to connect to the registry, then
you should override the checkConnectmethods. There are two checkConnect methods. The first
was discussed above, and the second checkConnect method has a third parameter that specifies
the security context of the request.

The following code illustrates how to do this:

System.setSecurityManager (new RMISecurityManager() {


public void checkConnect (String host, int port) {}
public void checkConnect (String host, int port, Object context) {}
});

The code above uses an anonymous inner class. Such a class is convenient when the class will
only be used to construct an object in one place, as in this example. Of course, one could also
define the subclass of RMISecurityManager in the usual way.

Defining and installing a security manager was the original technique for specifying a security
policy in Java. Unfortunately, it is very difficult to design such a class so that it does not leave
any security holes. For this reason, a new technique was introduced in Java 1.2, which is
backward compatible with the old technique. In the default security manager, all check methods
(except checkPermission) are implemented by calling the checkPermission method. The type of
permission being checked is specified by the parameter of type Permission passed to
the checkPermission method. For example, thecheckConnect method calls checkPermission with
a SocketPermission object. The default implementation of checkPermission is to call
the checkPermission method of the AccessController class. This method checks whether the
specified permission is implied by a list of granted permissions. ThePermissions class is used for
maintaining lists of granted permissions and for checking whether a particular permission has
been granted.

This is the mechanism whereby the security manager checks permissions, but it does not explain
how one specifies or changes the security policy. For this purpose there is yet another class,
named Policy. Like SecurityManager, each program has a current security policy that can be
obtained by callingPolicy.getPolicy(), and one can set the current security policy
using Policy.setPolicy, if one has permission to do so. The security policy is typically specified
by a policy configuration file (or "policy file" for short) which is read when the program starts
and any time that a request is made to refresh the security policy. The policy file defines the
permissions contained in a Policy object. It is not inaccurate to think of the policy file a kind of
serialization of a Policy object (except that a policy file is intended to be readable by humans as
well as by machines). As an example, the following will grant all permissions of any kind to
code residing in the RMI directory on the C: drive:

grant codeBase "file:C:/RMI/-" {


permission java.security.AllPermission;
};

The default security manager uses a policy that is defined in a collection of policy files. For the
locations of these files see the documentation of the policytool program. If one wishes to grant
additional permissions, then one can specify them in a policy file and then request that they be
loaded using options such as the following:

java –D java.security.manager –D java.security.policy=policy-file MyClass


Both of the "-D" options specify system properties. The first system property has the same effect
as executing the following statement as the first statement in your program:
System.setSecurityManager (new SecurityManager());
The second system property above causes the specified policy-file (which is specified with a
URL) to be added to the other policy files when defining the entire security policy.
The policytool can be used to construct the policy file, but one can also use any text editor.

As if this wasn't already complicated enough, there is yet another way to deal with the problem
of downloading Serializable classes. The command-line option –D
java.rmi.server.codebase=code-base specifies a location from which Serializable classes may be
downloaded. Of course, your security manager must recognize this system property, and not all
of them will do so. Furthermore, as mentioned earlier, this is only necessary if you actually need
to download Serializable classes.

1. Write a program using Java RMI to add two numbers provided by the
client.

Algorithm:

1. Create the interface Add with the method to add two numbers. The method is implemented
by the class that inherits it.

2. The client RMI interacts with the server with the two numbers.

3. The server creates an object of the class that inherits the interface and implements the query.

4. The answer is sent back to the client.


Interface creation:

import java.rmi.*;

public interface Adder extends Remote{

public int add(int x,int y)throws RemoteException;


}

Adder Remote class:

import java.rmi.*;
import java.rmi.server.*;

public class AdderRemote extends UnicastRemoteObject implements Adder{

AdderRemote()throws RemoteException{
super();
}

public int add(int x,int y){return x+y;}

Server :
import java.rmi.*;
import java.rmi.registry.*;

public class MyServer{

public static void main(String args[]){


try{

Adder stub=new AdderRemote();


Naming.rebind("rmi://localhost:5000/sonoo",stub);
}catch(Exception e){System.out.println(e);}
}

}
Client:
import java.rmi.*;

public class MyClient{

public static void main(String args[]){


try{
Adder stub=(Adder)Naming.lookup("rmi://localhost:5000/sonoo");
System.out.println(stub.add(34,4));
}catch(Exception e){}
}
}

Input: Numbers : 2 3
Output : Answer : 5

2. Write a program to implement Factorial of a number using RMI.


Algorithm:

1. Create a server client communication using RMI.

2. Implement a method to compute the factorial of a number at the server side.

3. Give the required input from the client.

4. Server computes the results and sends it to the client.

Interface Creation and Implementation:

import java.rmi.*;
public interface Factorial extends Remote
{
public int factorial(int n) throws RemoteException;
}

import java.rmi.*;
import java.rmi.server.*;
public class RemoteFactorial extends UnicastRemoteObject implements Factorial
{
RemoteFactorial() throws RemoteException
{
super();
}
public int factorial(int n)
{
int fact=1;;
for(int i=n;i>0;i--)
{
fact = fact*i;
}
return fact;
}
}

Server:
import java.rmi.*;
import java.rmi.registry.*;
public class FactorialServer
{
public static void main(String args[])
{
try
{
Factorial stub = new RemoteFactorial();
Naming.rebind("rmi://localhost:5001/sunil",stub);
}
catch(Exception e)
{
System.out.println("Exception: "+e);
}
}
}

Client:
import java.rmi.*;
import java.rmi.registry.*;
import java.util.Scanner;
public class FactorialClient
{
public static void main(String args[])
{
try
{
Scanner input = new Scanner(System.in);
Factorial stub = (Factorial) Naming.lookup("rmi://localhost:5001/sunil");
System.out.println("Please enter the number");
int n = input.nextInt();
int fact = stub.factorial(n);
System.out.println("Factorial is: "+fact);
}
catch(Exception e)
{
System.out.println("Exception: "+e);
}
}
}

Input: Enter the number : 4


Output : Factorial is : 24

.1 Write a program to implement the DNS server by using RMI.


Algorithm:

1. Create the interface .

2. Implement the methods of the interface for searching the query sent by the client.

3. The client sends the input string.

4. The server sends the required answer back to the client.

Interface Creation and Implementation.

import java.rmi.*;
public interface DNS extends Remote
{
public String url_to_ip(String url) throws RemoteException;
}

import java.rmi.*;
import java.rmi.server.*;
import java.io.*;
public class RemoteDNS extends UnicastRemoteObject implements DNS
{
RemoteDNS() throws RemoteException
{
super();
}
public String url_to_ip(String url)
{
String filename="dns.txt",data,file_url = "",file_ip="";
int i;
File f=new File(filename);
boolean flag = false ;
try
{
BufferedReader in = new BufferedReader(new FileReader(f));
while((data=in.readLine())!=null){
i = data.indexOf('#');
file_url = data.substring(0,i);
file_ip = data.substring(i+1,data.length());
if(file_url.equals(url))
{
flag = true;
break;
}
}
if(flag == false)
{
file_ip = "Entry Not Available";
}
}
catch(FileNotFoundException e)
{
System.out.println("Error: "+e);
}
catch(IOException ex)
{
System.out.println("IOException: "+ex);
}
return file_ip;
}
}

Server:

import java.rmi.*;
import java.rmi.registry.*;
public class DNSServer
{
public static void main(String args[])
{
try
{
DNS stub = new RemoteDNS();
Naming.rebind("rmi://localhost:7000/sunil",stub);
}
catch(Exception e)
{
System.out.println("Exception: "+e);
}
}
}

Client:

import java.rmi.*;
import java.rmi.registry.*;
import java.util.Scanner;
import java.io.DataInputStream;
public class DNSClient
{
public static void main(String args[])
{
try
{
DataInputStream input = new DataInputStream(System.in);
DNS stub = (DNS) Naming.lookup("rmi://localhost:7000/sunil");
System.out.println("Please enter the host address");
String url = input.readLine();
String ip = stub.url_to_ip(url);
System.out.println("The IP is: "+ip);
}
catch(Exception e)
{
System.out.println("Exception: "+e);
}
}
}

Input:

Please enter the host address : www.abc.com


Output:

Entry available: 10.10.0.1

You might also like