Ex. No.
1 Socket Programming In Java Two Way Communication
Description
A socket is one endpoint of a two-way communication link between two programs running on
the network. A socket is bound to a port number so that the TCP layer can identify the
application that data is destined to be sent to.
Procedures:
Server Side
1. Creating a ServerSocket,
2. Binding it to an address,
3. Waiting for clients,
4. When accepting a connection from a client the server creates another socket for
exchanging data with the client.
Client Side
1. Creating a socket,
2. Obtaining streams associated with the socket,
3. Sending requests to the server by means of the output stream,
4. Receiving server responses from the input stream,
5. Closing streams,
6. Closing the socket.
Program:
Server Side
import java.io.*;
import java.net.*;
public class Server
{
public static void main(String[] args) throws Exception
{
ServerSocket sersock = new ServerSocket(3000);
System.out.println("Server ready for chatting");
Socket sock = sersock.accept( );
// reading from keyboard (keyRead object)
BufferedReader keyRead = new BufferedReader(new InputStreamReader(System.in));
// sending to client (pwrite object)
OutputStream ostream = sock.getOutputStream();
PrintWriter pwrite = new PrintWriter(ostream, true);
// receiving from server ( receiveRead object)
InputStream istream = sock.getInputStream();
BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));
String receiveMessage, sendMessage;
while(true)
{
if((receiveMessage = receiveRead.readLine()) != null)
{
System.out.println(receiveMessage);
}
sendMessage = keyRead.readLine();
pwrite.println(sendMessage);
pwrite.flush();
}
}
}
Client Side:
import java.io.*;
import java.net.*;
public class Client
{
public static void main(String[] args) throws Exception
{
Socket sock = new Socket("localhost", 3000);
// reading from keyboard (keyRead object)
BufferedReader keyRead = new BufferedReader(new InputStreamReader(System.in));
// sending to client (pwrite object)
OutputStream ostream = sock.getOutputStream();
PrintWriter pwrite = new PrintWriter(ostream, true);
// receiving from server ( receiveRead object)
InputStream istream = sock.getInputStream();
BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));
System.out.println("Start the chitchat, type and press Enter key");
String receiveMessage, sendMessage;
while(true)
{
sendMessage = keyRead.readLine(); // keyboard reading
pwrite.println(sendMessage); // sending to server
pwrite.flush(); // flush the data
if((receiveMessage = receiveRead.readLine()) != null) //receive from server
{
System.out.println(receiveMessage); // displaying at DOS prompt
}
}
}
}
Ex. No.02 REMOTE PROCEDURE CALL
Description:
Remote Procedure Call (RPC) is a protocol that one program can use to request a service from a
program located in another computer on a network without having to understand the network's
details. A procedure call is also sometimes known as a function call or a subroutine call.
Procedure:
1. The client calls the client stub. The call is a local procedure call, with parameters pushed
on to the stack in the normal way.
2. The client stub packs the parameters into a message and makes a system call to send the
message. Packing the parameters is called marshalling.
3. The client's local operating system sends the message from the client machine to the
server machine.
4. The local operating system on the server machine passes the incoming packets to
the server stub.
5. The server stub unpacks the parameters from the message. Unpacking the parameters is
called unmarshalling.
6. Finally, the server stub calls the server procedure. The reply traces the same steps in the
reverse direction.
Server.java
import java.io.*;
import java.net.*;
class Server
{
public static void main(String[] args) throws Exception
{
ServerSocket sersock = new ServerSocket(3000);
System.out.println("Server ready");
Socket sock = sersock.accept( );
BufferedReader keyRead = new BufferedReader(new InputStreamReader(System.in));
OutputStream ostream = sock.getOutputStream();
PrintWriter pwrite = new PrintWriter(ostream, true);
InputStream istream = sock.getInputStream();
BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));
String receiveMessage, sendMessage,fun;
int a,b,c;
while(true)
{
fun = receiveRead.readLine();
if(fun != null)
System.out.println("Operation : "+fun);
a = Integer.parseInt(receiveRead.readLine());
System.out.println("Parameter 1 : "+a);
b = Integer.parseInt(receiveRead.readLine());
if(fun.compareTo("add")==0)
{
c=a+b;
System.out.println("Addition = "+c);
pwrite.println("Addition = "+c);
}
if(fun.compareTo("sub")==0)
{
c=a-b;
System.out.println("Substraction = "+c);
pwrite.println("Substraction = "+c);
}
if(fun.compareTo("mul")==0)
{
c=a*b;
System.out.println("Multiplication = "+c);
pwrite.println("Multiplication = "+c);
}
if(fun.compareTo("div")==0)
{
c=a/b;
System.out.println("Division = "+c);
pwrite.println("Division = "+c);
}
System.out.flush();
}
}
}
Client.java
import java.io.*;
import java.net.*;
class Client
{
public static void main(String[] args) throws Exception
{
Socket sock = new Socket("localhost", 3000);
BufferedReader keyRead = new BufferedReader(new InputStreamReader(System.in));
OutputStream ostream = sock.getOutputStream();
PrintWriter pwrite = new PrintWriter(ostream, true);
InputStream istream = sock.getInputStream();
BufferedReader receiveRead = new BufferedReader(new InputStreamReader(istream));
System.out.println("Client ready, type and press Enter key");
String receiveMessage, sendMessage,temp;
while(true)
{
System.out.println("\nEnter operation to perform(add,sub,mul,div)....");
temp = keyRead.readLine();
sendMessage=temp.toLowerCase();
pwrite.println(sendMessage);
System.out.println("Enter first parameter :");
sendMessage = keyRead.readLine();
pwrite.println(sendMessage);
System.out.println("Enter second parameter : ");
sendMessage = keyRead.readLine();
pwrite.println(sendMessage);
System.out.flush();
if((receiveMessage = receiveRead.readLine()) != null)
System.out.println(receiveMessage);
}
}
}
Ex. No.03 THREADING
Write a program that executes two threads. Create the threads by implementing Runnable
interface.
a. One thread display “Hello!” every 1 second 10 times, and
b. Another thread display “Hey” every 2 seconds 10 times.
Definition:
A thread is the flow of execution, from beginning to end, of a task in a program. A task is a
program unit that is executed independently of other parts of the program. A thread provides the
mechanism for running a task. With Java, you can launch multiple threads from a program
concurrently. These threads can be executed simultaneously in multiprocessor systems.
Multithreading can make your program more responsive and interactive, as well as enhance
performance.
Description:
Tasks are objects. To create tasks, you have to first declare a class for tasks. An application that
creates an instance of Thread must provide the code that will run in that thread. There are two
ways to do this:
1. By implementing the runnable interface
2. By extending the Thread class
Program:
Step 1: Implement the HelloThread class
public class HelloThread implements Runnable {
public void run() {
try {
for (int i = 1; i <= 10; i++) {
System.out.print(" Hello! ");
Thread.sleep(1000);
}
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Step 2: Implement the HeyThread class
public class HeyThread extends Thread {
public void run() {
try {
for (int i = 1; i <= 10; i++) {
System.out.print(" Hey! ");
Thread.sleep(2000);
}
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Step 3: Implementing a Test class which creates and runs both threads.
public class ThreadTest {
public static void main(String args[]) {
HelloThread ht = new HelloThread();
Thread t = new Thread(ht);
HeyThread heyt = new HeyThread();
t.start();
heyt.start();
}
}
Ex. No.04 RING BASED LEADER ELECTION ALGORITHM
Definition:
A ring network is a connected-graph topology in which each node is exactly connected to two
other nodes, i.e., for a graph with n nodes, there are exactly n edges connecting the nodes. A ring
can be unidirectional, which means processors only communicate in one direction (a node could
only send messages to the left or only send messages to the right), or bidirectional, meaning
processors may transmit and receive messages in both directions (a node could send messages to
the left and right).
Description:
The algorithm is suitable for a collection of processes arranged in a logical ring. Each process pi
has a communication channel to the next process in the ring, p i + 1 mod N , and all messages
are sent clockwise around the ring. The goal of this algorithm is to elect a single process called
the coordinator, which is the process with the largest identifier. Initially, every process is marked
as a non-participant in an election. Any process can begin an election. It proceeds by marking
itself as a participant, placing its identifier in an election message and sending it to its clockwise
neighbour. When a process receives an election message, it compares the identifier in the
message with its own. If the arrived identifier is greater, then it forwards the message to its
neighbour. If the arrived identifier is smaller and the receiver is not a participant, then it
substitutes its own identifier in the message and forwards it; but it does not forward the message
if it is already a participant. On forwarding an election message in any case, the process marks
itself as a participant.
A ring-based election algorithm
Note: The election was started by process 17. The highest process identifier encountered
so far is 24.
If, however, the received identifier is that of the receiver itself, then this process’s identifier must
be the greatest, and it becomes the coordinator. The coordinator marks itself as a non-participant
once more and sends an elected message to its neighbour, announcing its election and enclosing
its identity. When a process pi receives an elected message, it marks itself as a nonparticipant,
sets its variable electedi to the identifier in the message and, unless it is the new coordinator,
forwards the message to its neighbour. It is easy to see that condition E1 is met. All identifiers
are compared, since a process must receive its own identifier back before sending an elected
message. For any two processes, the one with the larger identifier will not pass on the other’s
identifier. It is therefore impossible that both should receive their own identifier back.
Condition E2 follows immediately from the guaranteed traversals of the ring
(there are no failures). Note how the non-participant and participant states are used so
that duplicate messages arising when two processes start an election at the same time are
extinguished as soon as possible, and always before the ‘winning’ election result has
been announced.
Program:
import java.util.Scanner;
class Process {
int processId;
boolean active;
public Process(int processId) {
this.processId = processId;
active = true;
}
}
public class RingElection {
private Scanner consoleInput;
private Process[] process;
private int NosOfProcess;
public RingElection() {
System.out.println("\n\t\t==:Ring Coordinator Election Algorithm:==\n");
consoleInput = new Scanner(System.in);
}
public void getInput() {
System.out.println("Enter number of process in ring: ");
NosOfProcess = consoleInput.nextInt();
process = new Process[NosOfProcess];
for (int i = 0; i < NosOfProcess; i++) {
System.out.print("Enter Process ID of p" + i + ": ");
int pid = consoleInput.nextInt();
initializeProcess(i, pid);
}
sortProcess();
putOutput();
}
private void initializeProcess(int i, int pid) {
process[i] = new Process(pid);
}
public void conductElection() {
try{
Thread.sleep(2000);
}catch(Exception e ){
System.out.println(e);
}
System.out.println("process "+ process[getMax()].processId +" Fail");
process[NosOfProcess-1].active = false;
while(true){
System.out.print("Conduct Election?\nyes or exit: ");
String choice = consoleInput.next();
if("yes".equals(choice) || "Yes".equals(choice) || "y".equals(choice) || "Y".equals(choice))
{
System.out.println("Election initiated by: ");
int initiatorProcess = consoleInput.nextInt();
for(int i = 0; i< NosOfProcess; i++){
if(process[i].processId == initiatorProcess){
initiatorProcess = i;
break;
}
}
int prev = initiatorProcess;
int next = prev+1;
while(true){
if(process[next].active) {
System.out.println("Process "+ process[prev].processId +" pass message to
process "+process[next].processId );
prev = next;
}
next = (next+1) % NosOfProcess;
if(next == initiatorProcess) {
break;
}
}
System.out.println("Process "+ process[getMax()].processId +" becomes coordinator");
} else {
System.exit(0);
}
}
}
public void putOutput(){
System.out.println("Processes in the ring: ");
for(int i = 0; i < NosOfProcess; i++){
System.out.print(process[i].processId +", active: "+ process[i].active);
if(i == getMax()){
System.out.print(", Coordinator\n");
}else {
System.out.print("\n");
}
}
}
private void sortProcess() {
for (int i = 0; i < NosOfProcess - 1; i++) {
for (int j = 0; j < (NosOfProcess - i) -1; j++) {
if (process[j].processId > process[j + 1].processId) {
int temp = process[j].processId;
process[j].processId = process[j + 1].processId;
process[j + 1].processId = temp;
}
}
}
}
private int getMax(){
int max = 0, indexOfMax = 0;
for(int i = 0; i < NosOfProcess; i++){
if(process[i].active && max <= process[i].processId ) {
max = process[i].processId;
indexOfMax = i;
}
}
return indexOfMax;
}
public static void main(String arg[]) {
System.out.println("BHAGYASHREE MEHTA [0802IT121014]");
RingElection ringElection = new RingElection();
ringElection.getInput();
ringElection.conductElection();
}
}
Ex. No.05 MUTUAL EXCLUSION
Definition:
A mutual exclusion (mutex) is a program object that prevents simultaneous access to a shared resource.
This concept is used in concurrent programming with a critical section, a piece of code in which
processes or threads access a shared resource.
Description:
In order to ensure the integrity of data, shared data cannot be used by more than ONE process at
the same time. The following is an example showing the problem if there is no mutual exclusion:
Two transactions are trying to update a bank account at the same time, one
making a deposit while the other is making a withdrawal.
Transaction 1 Transaction 2
READ Balance READ Balance
ADD 2000 Subtract 500
WRITE Balance WRITE Balance
Let Balance = 1000 initially. The first transaction after executing READ and
ADD, will have 3000 in the accumulator. If the second transaction gets the
CPU and executes the first two instruction before releasing the CPU to
transaction 1 again, the final value of Balance will be 500 instead of 2500.
This problem can be solved if each process has exclusive access to the
variable “Balance”. That is:
all others have to wait while one updates the shared variables
this is called “mutual exclusion”
Program:
import java.util.Random;
class Util {
public static void pause(int low, int high) {
Random r = new Random();
int R = r.nextInt(high-low) +low;
try {
Thread.sleep(R);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static int random(int low, int high) {
Random r = new Random();
int R = r.nextInt(high-low) + low;
return R;
}
}
class Printer extends Thread {
static Object mutex = new Object();
public void run() {
for(;;) {
synchronized (mutex) {
System.out.print("-");
Util.pause(100, 300);
System.out.print("/");
}
Util.pause(0, 200);
}
}
}
class MutualExclusion {
public static void main(String[] args) {
new Printer().start();
new Printer().start();
}
}