Program 1 Two Chat Systems Solution

$30.00

Description

1. Purpose

The goal of this assignment is to learn how to use Java-based TCP communication by designing and

implementing a chat client and server program. We also implement consistent ordering in broadcasting

messages from one client to all other clients through a central server, as well as causal ordering in

exchanging messages among clines without using central server.

2. Message Ordering

As covered in class material, it is necessary to distinguish several message ordering schemes depending

on the distributed application. Schemes include absolute ordering, consistent ordering, causal ordering,

and first-in-first-out ordering (listed here from the tightest to the loosest consistency). Although absolute

ordering is accurate to keep track of who spoke first and who responded second in Internet chatting, it

needs a global clock among clients, which is almost impossible over Internet. Therefore, we implement

consistent ordering and causal ordering.

In consistent ordering, messages are simply delivered in the same order to each client regardless of their

stamp. This means, although message A was created before message B, message B may be delivered to all

chat participants first, but it is guaranteed that all users receive message B and later message A. We use a

centralized algorithm to implement this consistent ordering. More specifically, each chat client needs to

contact a central chat server that then broadcasts the client message to all the clients, in which manner

the server works as a focal point of consistent message ordering.

In causal ordering, a message is delivered to each receiver before it receives all the subsequent messages

generated by a third party. For this purpose, each computing node maintains a vector of stamps, each

counting send/receive events at node i (where 0 <= i < #hosts). When a sender sends a message,

it also includes its own vector stamp in the message. The receiver receives the message only when all

stamps in the source j’s vector are smaller or equal to those in the receiver’s vector, except that stamp j

in the source j’s vector is one larger than that in the receiver’s vector.

Part 1: Chats in Consistent Order

A. Chat Client

The chat’s client program should be invoked with arguments: client name, a server IP name, and a server

port, for example

[css434@uw1-320-20 hw1]$ java ChatClient jsmith uw1-320-10 12345

The client program establishes a socket connection to the server, generates a pair of data input and

output streams from this connection, sends its client name with writeUTF( ), and finally goes in an

infinite loop where it repeats reading a new keyboard input, (i.e., stdin) if there is any, writing this

message to the server, checking if there is a new message arrived from the server, and displaying it to the

display, (i.e., to stdout). If the client detects EOF through stdin, it leaves the loop and terminates itself.

The following shows the client program, (ChatClient.java):

/**

  • ChatClient.java:<p>

  • realizes communication with other clients through a central chat server.

  • @author Munehiro Fukuda (CSS, University of Washington, Bothell)

* @since

1/23/05

* @version

2/5/05

*/

import java.net.*;

// for Socket

import java.io.*;

// for IOException

public class ChatClient {

private

Socket socket;

// a socket connection to a chat server

private

InputStream rawIn;

// an input stream from the server

private

DataInputStream in;

// a filtered input stream from the server

private

DataOutputStream out;

// a filtered output stream to the server

private

BufferedReader stdin;

// the standard input

/**

  • Creates a socket, contacts to the server with a given server ip name

  • and a port, sends a given calling user name, and goes into a “while”

  • loop in that:<p>

*

  • <ol>

  • <li> forward a message from the standard input to the server

  • <li> forward a message from the server to the standard output

  • </ol>

*

* @param name

the calling

user name

* @param server

a

server

ip

name

* @param port

a

server

port

*/

public ChatClient( String name, String server, int port ) {

  • Create a socket, register, and listen to the server try {

// Connect to the server

socket = new Socket( server, port );

rawIn = socket.getInputStream( );

// Create an input, an output, and the standard output stream.

in = new DataInputStream( rawIn );

out = new DataOutputStream( socket.getOutputStream( ) );

stdin = new BufferedReader( new InputStreamReader( System.in ) );

  • Send the client name to the server out.writeUTF( name );

while( true ) {

    • If the user types something from the keyboard, read it from

    • the standard input and simply forward it to the server

if ( stdin.ready( ) ) {

String str = stdin.readLine( );

  • no more keyboard inputs: the user typed ^d. if ( str == null )

1 of 5 , 4:58 PM

OneNote Online https://onenote.officeapps.live.com/o/onenoteframe.aspx?ui=en-US&rs=…

break;

out.writeUTF( str );

}

  • If the server gives me a message, read it from the server

  • and write it down to the standard output.

if ( rawIn.available( ) > 0 ) {

String str = in.readUTF( );

System.out.println( str );

}

}

// Close the connection. That’s it. socket.close( );

} catch ( Exception e ) { e.printStackTrace( );

}

}

/**

  • Usage: java ChatClient <your_name> <server_ip_name> <port>

  • @param args Receives a client user name, a server ip name, and its port

  • in args[0], args[1], and args[2] respectively.

*/

public static void main( String args[] ) {

// Check # args.

if ( args.length != 3 ) {

System.err.println( “Syntax: java ChatClient <your name> ” +

“<server ip name> <port>” );

System.exit( 1 );

}

// convert args[2] into an integer that will be used as port.

int port = Integer.parseInt( args[2] );

  • instantiate the main body of ChatClient application. new ChatClient( args[0], args[1], port );

}

}

Figure: source code for ChatClient.java

The code logic is very simple. It checks the number of arguments, and instantiates a ChatClient object that

implements the algorithm above.

There are some Java specific classes you should keep in mind:

InputSteam This is a byte-streamed socket input. To read messages from an established

socket, you must first obtain this object through getInputStream( ) from the

socket. Messages must be bytes.

OutputStream This is a byte-streamed socket output. To write messages to an established

socket, you must first obtain this object through getOutputStream( ) from

the socket. Messages must be bytes.

DataInputStream This filters a given InputStream object, so that you can receive messages in any

primitive types other than bytes. The readUTF( ) reads in a string that has

been encoded using a modified UTF-8 format.

DataOutputSteam This filters a given OutputStream object, so that you can send messages in

any primitive types other than bytes. The writeUTF( ) writes in a string that

has been encoded using a modified UTF-8 format.

B. Chat Server

A chat server program should be invoked with one argument, the server’s port:

[css434@uw1-320-20 hw1]$ java ChatServer 12345

The server program establishes a server socket with a given port and creates a list of client connections

that is of course empty at the beginning. Thereafter, the server goes and remains in an infinite loop where

it repeats the following operations:

  1. Accept a new client socket connection if there is any,

  1. Read the client name with readUTF( ),

  1. Add this connection into the list of existing client connections.

  1. For each connection of the list,

    1. Receive a new message with readUTF( ) if there is any,

    1. Add the client name in front of the message received.

    1. Write this message to all clients through all connections of the list. Use writeUTF( ).

    1. Check if any errors have occurred when reading and writing a message. If so, remove this

connection from the list.

The server program is not shown because it is your assignment 🙂

Some programming hints:

  1. Java ServerSocket Class

Use the ServerSocket( int port ) constructor when instantiating a server socket. The accept( ) is a blocking call as default. However, we do not want to be blocked upon accept( ). Use setSoTimeout( 500 ) so that the accept( ) can return in 500msec. When calling accept( ), you have to use try{ } catch( SocketTimeoutExeception e ) { }. Whenever returning from accept( ), check if the return value has a reference to a new socket or null. If it has a reference, you got a new connection and thus can add it to a list of connections.

  1. Connection Class

I recommend you should design your Connection class whose instance can maintain a client socket connection and provide readMessage( ) and writeMessage( ) functions. They are used to read a new message with readUTF( ) and write a message with writeUTF( ). When an error has occurred in a message read and/or a write, record this error, so that you can delete this connection later. Note: this is optional.

Again, readUTF( ) is a blocking call as default. Make sure that the socket has some data to read through readUTF( ) before actually calling readUTF( ). For this purpose, Use the available( ) of the InputStream( ) class that you should obtain from the socket.

2 of 5 , 4:58 PM

OneNote Online https://onenote.officeapps.live.com/o/onenoteframe.aspx?ui=en-US&rs=…

Part 1 Statement of Work

Design and implement ChatServer.java according to the above server specification. Compile your

ChatServer.java and the provided ChatClient.java (located in the uw1-320 machines under:

~css434/hw1/ directory).

Run them as follows:

  1. Choose four different machines in uw1-320.

  1. Start ChatServer first on one of these machines.

  1. Run ChatClient on each of the other three machines with a different client name such as gandalf, frodo, and khaleesi (or whatever you like, sample output is using “Disney-friendly” Mickey, Mini, Goofy J).

  2. Test if a client message is broadcast through the server to all the clients.

  1. Take a snapshot of your program’s execution (e.g., type “import –window root X.jpeg” at an xterm)

Part 2. Chats in Causal Order

A. Serverless Chat Client

In this case, the program does not use a central server. We will name this program Chat.java (which

can be found under /CSSDIV/classes/434/hw1 ). All computing nodes have to do is just run this

chat client with the same arguments:

[css434@uw1-320-20 hw1]$ java Chat 12345 uw1-320-20 uw1-320-21 uw1-320-22

The first argument is the IP port, (i.e. the last five digits of your student ID) used to establish a TCP

connection to each remote computing node. The following arguments are a list of computing nodes that

participate in the same chatting session. The order of computing nodes must be the same at each node.

The main function verifies the arguments and instantiates a Chat class. The constructor first creates a

complete TCP network among all computing nodes. To broadcast a local message to all the other chat

members, we repeat sending the message to each of ObjectOutputStreams, outputs[i] where

  • <= i < #hosts, (i.e., hosts.length). To receive a message from a remote chat member, we read a message from an ObjectInputStream,inputs[i]. The following shows the message broadcasting and receiving portion of this serverless client program, (Chat.java):

The file Chat.java contains the following code. You must use Chat.java with your program.

  • now goes into a chat while ( true ) {

    • read a message from keyboard and broadcast it to all the others. if ( keyboard.ready( ) ) {

  • since keyboard is ready, read one line. String message = keyboard.readLine( );

if ( message == null ) {

    • keyboard was closed by “^d”

break; // terminate the program

}

  • broadcast a message to each of the chat members. for ( int i = 0; i < hosts.length; i++ )

if ( i != rank ) {

    • of course I should not send a message to myself

outputs[i].writeObject( message );

outputs[i].flush( ); // make sure the message was sent

}

}

  • read a message from each of the chat members for ( int i = 0; i < hosts.length; i++ ) {

    • to intentionally create a misordered message deliveray,

    • let’s slow down the chat member #2.

try {

if ( rank == 2 )

Thread.currentThread( ).sleep( 5000 ); // sleep 5 sec.

} catch ( InterruptedException e ) {}

// check if chat member #i has something

if ( i != rank && indata[i].available( ) > 0 ) {

  • read a message from chat member #i and print it out

  • to the monitor

try {

String message = ( String )inputs[i].readObject( );

System.out.println( hosts[i] + “: ” + message );

} catch ( ClassNotFoundException e ) {}

}

}

}

Figure: Chat.java

B. Creating a miss-ordered delivery

Look at the code snippet in blue above. It delays the third chat member, (i.e., rank 2) for 5 seconds. This

prevents the third chat member from receiving messages from the others in the causal order. For

instance, let’s assume that the first chat member writes “Go skiing?” and thereafter the second chat

member responds “Yes”.

[css434@uw1-320-20 hw1.new]$ java Chat 12345 uw1-320-20 uw1-320-21 uw1-320-22

port = 12345, rank = 0, localhost = uw1-320-20

accepted from uw1-320-21.uwb.edu

accepted from uw1-320-22.uwb.edu

Go skiing?

Uw1-320-21: Yes

css434@uw1-320-21 hw1.new]$ java Chat 12345 uw1-320-20 uw1-320-21 uw1-320-22

port = 12345, rank = 1, localhost = uw1-320-21

accepted from uw1-320-22.uwb.edu

connected to uw1-320-20

uw1-320-21: Go skiing?

Yes

css434@uw1-320-22 hw1.new]$ java Chat 12345 uw1-320-20 uw1-320-21 uw1-320-22

port = 12345, rank = 2, localhost = uw1-320-22

connected to uw1-320-22

connected to uw1-320-21

uw1-320-21:Yes

uw1-320-20: Go skiing?

As shown above, the third chat member (at uw1-320-22) mistakenly receives “Yes” first and “Go skiing?”

3 of 5 , 4:58 PM

OneNote Online https://onenote.officeapps.live.com/o/onenoteframe.aspx?ui=en-US&rs=…

which is not the causal order.

Part 2 Statement of Work

Insert additional code into Chat.java to implement the causal ordering so that all chat members can

receive a message before its subsequent messages generated by the third party. For instance, “Go skiing?”

and “Yes” messages should be printed out in this order at all computing nodes like:

[css434@uw1-320-20 hw1.new]$ java Chat 12345 uw1-320-20 uw1-320-21 uw1-320-22

port = 12345, rank = 0, localhost = uw1-320-20

accepted from uw1-320-21.uwb.edu

accepted from uw1-320-22.uwb.edu

Go skiing?

Uw1-320-21: Yes

css434@uw1-320-21 hw1.new]$ java Chat 12345 uw1-320-20 uw1-320-21 uw1-320-22

port = 12345, rank = 1, localhost = uw1-320-21

accepted from uw1-320-22.uwb.edu

connected to uw1-320-20

uw1-320-21: Go skiing?

Yes

css434@uw1-320-22 hw1.new]$ java Chat 12345 uw1-320-20 uw1-320-21 uw1-320-22

port = 12345, rank = 2, localhost = uw1-320-22

connected to uw1-320-22

connected to uw1-320-21

uw1-320-20: Go skiing?

uw1-320-21:Yes

In your implementation, each computing node must maintain a vector of stamps, where each element i

counting send/receive events at node i. Before broadcasting a new message, the local host should

increment its corresponding element of the vector. It should send the message as well as the vector.

Whenever receiving a new message from a sender j, you also have to receive this sender’s vector and

compare its contents with the local vector contents. The comparison must be achieved as follows:

  • For each element i

    • If i == j, the sender’s vector[i] must be one larger than the local host’s vector[i].

    • Otherwise the sender’s vector[i] must be smaller than or equal to the local host’s vector[i].

If these conditions are satisfied, you can accept and print out the message as incrementing the local host’s

vector[j]. Otherwise, keep this message and vector in a waiting list, and check it later when you

receive another message.

Note: you must not modify any of the original code, you can only add your new code into Chat.java.

After implementing your causal-ordered chat client, run it as follows:

  1. Choose three different machines in uw1-320.

  1. Run Chat on each of the other three machines

  1. Test if they exchange messages in the causal order with the above scenario: “Go skiing?” and “Yes”.

  1. Take a snapshot of your program’s execution

Deliverables

The homework is due as specified on Canvas. You have to electronically submit the following as two

separate files (i.e., do not put everything in a zip):

  1. Report: a PDF or MS Word file. The report

    1. Must contain discussions as specified in the rubric

    1. Must also include execution outputs in the

  1. Source code: A ZIP file containing all your source code (i.e., all .java files) as follows

    1. Create a folder and name it Prog1

    1. Place all your source code files inside that folder

    1. ZIP the folder as Prog1.zip (this is what you submit to Canvas)

Again: The ZIP file should only contain source code, not the report. Points will be deducted upon

failure to follow these instructions.

Rubric

Criteria

Grade

Documentation of your algorithm including explanations and illustrations in one

5pts

or two pages.

1.

Part 1 Algorithm (consistent ordering): 2.5pts

2.

Part 2 Algorithm (causal ordering): 2.5pts

Source code that adheres good modularization, coding style, and an appropriate

5pts

amount of comments.

1.

Part 1: ChatServer.java

a.

A use of non-blocking accept (0.5pts)

b.

A use of non-blocking read (0.5pts)

c.

Total ordering maintained (0.5pts)

d.

Code completeness (0.5pts)

e.

Coding style and readability (0.5pts)

2.

Part 2: Chat.java

a.

A use of vector messages (0.5pts)

b.

A correct delivery check of vector messages (0.5pts)

c.

A correct queue to maintain vector messages (0.5pts)

d.

Code completeness (0.5pts)

e.

Coding style and readability (0.5pts)

Execution output such as a snapshot of your display/windows or contents of

5pts

standard output redirected to a file.

1.

Part 1’s outputs: 2.5pts

a.

A plenty of correct results receive 2.5pts

b.

Insufficient and/or minor errors receive 2pts

c.

Incomplete results receive 1.5pts

d.

No outputs receive 0pts

2.

Part 2’s outputs: 2.5pts

a.

A plenty of correct results receive 2.5pts

4 of 5 , 4:58 PM

OneNote Online https://onenote.officeapps.live.com/o/onenoteframe.aspx?ui=en-US&rs=…

  1. Insufficient and/or minor errors receive 2pts

  1. Incomplete results receive 1.5pts

  1. No outputs receive 0pts

Discussions about the efficiency of your algorithm and possible

5pts

performance/functional improvement in one page.

1.

Part 1 Algorithm (consistent ordering)

a.

Algorithm efficiency (1pt)

b. Performance and functional improvement (1.5pts)

2.

Part 2 Algorithm (causal ordering)

a.

Algorithm efficiency (1pt)

b. Performance and functional improvement( 1.5pts)

Total

20pts

5 of 5 , 4:58 PM


error: Content is protected !!