Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

CSCI 251 Concepts of Parallel and Distributed Systems

MessgeQueue

Consider the following UML description of the static class MessageQueue.

MessageQueue

+ Now : long

+ Show : bool

+ Enqueue (msg : string, iAm : int) :

+ Dequeue(timestamp : ref long, iAm : int, bailout : in bool) : string?

Static class MessageQueue is a self-purging, thread-safe, unbounded and interrogable queue intended to serve as a container for messages. producer / consumer monitor semantics are provided with the methods Enqueue and Dequeue, respectively. The implementation for MessageQueue is provided for this assignment and its use is required.

Read-only long property Now is the number of milliseconds since the MessageQueue was initialized and, if left running, would not roll over in your lifetime, so don’t worry about that complication.

Read/Write bool property Show is set to obtain debugging information pertaining to the operation of the MessageQueue. This property is initialized as false. (See program requirements, below.)

void Enqueue(string msg, int iAm) packages the specified message text, iAm—presumed to be a unique identifier of the enqueuing task—and the value of Now at the time Enqueue is invoked and enqueues the entire package. Enqueue then invokes Monitor.PulseAll to waken any blocked Dequeue requests. Enqueue will append the iAm to the front of the message text: []: msg.

string? Dequeue(ref long timestamp, int iAm, in bool bailout) returns the message text of the oldest enqueued package whose package timestamp is younger than that specified by the timestamp parameter, and whose package iAm is different than the specified iAm parameter value.

If there is no enqueued message package meeting those criteria, the requesting thread is blocked with Monitor.Wait to wait for a subsequent enqueue event. If the in reference parameter bailout becomes true before the criteria are met, the method returns null.

In addition to returning message text, the timestamp parameter (a ref variable) is updated to the package timestamp of the returned message. Thus,

long ts = 0;

bool stopTrying = false;

while (true) {

var msg = MessageQueue.Dequeue(ref ts, 0, stopTrying);

if (!stopTrying)

Console.WriteLine($”\”{msg}\” was enqueued @ {ts} milliseconds”);

else

break;

}

will return the text of all messages enqueued by all threads with identifiers other than 0. Those message texts will be returned in enqueue time order. If stopTrying becomes true during the performance of the loop, a blocked Dequeue will quit after a brief timeout and the loop should terminate.

Note that MessageQueue autonomously purges any message that has been enqueued for more than 5000 milliseconds! That means, if a message is not viewed in fewer than 5 seconds from the time it was enqueued, it will be lost.

Do This

First, go back and really read the material above, being certain that you understand the subtleties in the the operation of MessageQueue.

Using MessageQueue as the principal data structure, design and implement a multithreaded TCP server, following the pattern we have described several times in class, and outlined in class notes (and depicted below) in order to create a simple “chat room” application that will allow multiple TCP clients—telnet will work fine—to exchange messages. A message sent by any client should be received by all other clients active at the time the message is sent.

The implementation strategy is much different than that used for the chat room assignment last semester—don’t even waste your time looking for old versions. The new MessageQueue is considerably more sophisticated, being built on Monitors. Further, the required solution design uses a pair of tasks to implement the per client server so as to be much less problem-prone than last year’s solution approach.


Requirements

The ChatServer must bind to port 3003, listen for client connection requests and for each accepted request, launch a per-client chat server using a ThreadPool thread via the QueueUserWorkItem mechanism.

The Per-Client Chat Server (PCCS) is to be implemented as a single static method or nested procedure requiring a single parameter: the accepted client. The PCCS must be implemented with two tasks (using Task methods):

1. A “From Client” task that reads messages from the client’s user (ReadLineAsync) and enqueue those messages in the MessageQueue. If the client receives a null from ReadLineAsync, it means that the client’s user has closed the client (shut down telnet). The task should:

a. Signal the “To Client” task to complete and wait for it to do so;

b. Cause the PCCS to exit.

2. A “To Client” task that dequeues messaged from the MessageQueue and writes those messages to the client’s user (WriteLineAsync). If a signal is received from the “From Client” task to bail out, then exit the task.

The PCCS should send a “welcome” message to the client’s user when PCCS starts:

“Welcome to the Chat Room!”

The PCCS should also send a message to all active clients when a new client enters or exits the chat:

“Client has joined the chat.”

“Client has left the chat.”

Your program must accept a single optional argument, “show” which, if specified, indicates that the Show property of the MessageQueue is to be asserted (set to true).

Questions I Expect to Answer Many Times

A. How do you tell if the client’s user has terminated the client?

(Trick question, because it was already answered in the text above).

B. How do you signal that the PCCS should exit?

Believe it or not, simply setting a bool variable to true is sufficient, so long as that variable is shared by both the “From User” task (that will set the bool to true) and the “To User” task (that will pass the bool in every Dequeue request and appropriately test the value to know when it should exit).

C. Is it possible to send a message to all clients at once?

Yes. Reread the MessageQueue documentation.

D. Must my tasks be named/use named methods?

No. Feel free to use lambda with appropriate cautions!

E. Is this going to be a lot of work? (I’ll bet it is, grumble.)

I can’t answer that question, but my solution is 83 lines, including a fair number of comments.

F. Should I test my program before submitting it?

No, that’s what the graders are for! [sarcasm] Of course you should test your program!

G. That’s what I thought. How?


While you are at it, ram a lot of messages very quickly through one client and make sure that they are all received by all other clients… in order… nothing dropped.

There will doubtless be a lot of questions, including those already answered. I will open a Discussion Board. I will NOT answer any questions asked during the 48 hours preceding the submission time!