lu.se

Datavetenskap

Lunds Tekniska Högskola

Denna sida på svenska This page in English

A Chat System

Assignment #3: A Chat System

Objectives

The main objective of this exercise is to build a chat system enabling a group of participants to discuss in real time, where you will:

  • Understand connected communications
  • Create a TCP server
  • Create a multithreaded TCP server
  • Understand thread coordination
  • Write a program creating and running multiple coordinated threads to read and dispatch messages (consumer/producers)
  • Integrate the multithreaded producers/consumer to the server
  • Create a TCP client

Summary of the Work

Each group will have to:

  • Build a chat system that will enable users to connect to a server and to discuss in real time with all the connected participants;
  • Write a TCP server program that will receive the messages;
  • Create server threads that will handle the messages;
  • Integrate the monitor to coordinate the threads into the TCP server so that no message is lost.
  • Manage the list of active participants.
  • Write a TCP client.

Reading Assignments

Read (or reread) the following chapters from the book Java Network Programming by Elliotte Rusty Harold:

  • Chapter 3 on Java streams.
  • Chapter 4 on threads.
  • Chapters 8 and 9 on sockets and TCP programming.

Programming: TCP

Creating Connected Communications Using TCP

In this exercise, you will implement a connected server using the TCP protocol (EchoTCP1.java). The server will just echo a message until the user decides to disconnect.

  1. Define a protocol for the echo service.
  2. Use the ServerSocket class of the java.net package to create a connected service and bind it to the port number 30000 of your computer.
  3. Write a loop that accepts clients. Use the accept() method to receive a connection from a client and assign it to a Socket object.
  4. Identify the client using the getInetAddress() method of the Socket class and display it on the server screen.
  5. Use the getInputStream() and getOutputStream() methods of the Socket class to obtain the socket streams.
  6. Write a loop to read the client requests:
    • Read the client message using the read() method of the InputStream class and display it on the server screen.
    • Use the write() method of the OutputStream class to send a response to the client. To get the bytes from a String object, you can use the getBytes() method.
    • When the connection is finished, close it.
  7. To connect to the server, use telnet with the syntax:
    $ telnet machine port
    Telnet will then pass all the characters to the server.
    NOTE, In Mac OS X High Sierra (10.13) Apple has removed the telnet program for security reasons. To run the lab on a mac, use the netcat program instead (nc):
    $ nc localhost 30000
    Regarding security, telnet sends the text unencrypted using TCP, so anyone on the net can listen to these packages. Telnet is commonly used to login to a remote host, so the username and password is sent to the remote host unencrypted. It is not the telnet program itself that is unsecure, rather the common use case for it. For remote login, use encrypted communication, like ssh. Be aware, your chat system uses unencrypted communication, so don't write secrets in the chat...
  8. Does the server accept more than one client at a time? Why?

Creating a Concurrent Server

Your first TCP server could not handle more than one client at a time. To process parallel requests, each client must be paired with one thread of execution on the server.

In this exercise, you will improve the TCP server and write a new program (EchoServerTCP2.java) so that it can handle concurrent communications.

  1. In the server code, determine which part of the program answers the clients. How to run it in parallel?
  2. Encapsulate this part of code in a separate class derived from Thread.
  3. Modify the remaining code so that each time there is new connection, the server starts a new thread.
  4. Start the server and two or three clients. Run netstat -a. Observe the result and explain it.
  5. Try to launch a second server. Observe the result and explain it.

Programming: Thread Coordination

With the previous server, a client could not send messages to all the other participants (all the other clients). You will add this feature to your server and build a communication device between participants using threads and a shared structure. However, a major problem with threads is to coordinate them so that they do not interfere with each other. The goal of this part is to coordinate threads to read and dispatch messages.

In this part of the lab, you will review coordination mechanisms step by step. You will integrate the resulting methods in the server in the next part of the laboratory session.

Creating Threads

In this exercise, you will create and run concurrent threads.

  1. Write a thread class that writes its name on the screen five times. Derive your class from the Thread class and overload the run() method.
  2. Write a program that creates ten threads with a name and launches them.
  3. Insert a sleep() method in the loop of each thread with a random timing. Use the Math.random() method and observe the writing sequence.

Concurrent Access

Instead of writing their name on the screen, the threads will write it in a mailbox. Another thread will read the names and print them on the screen. The mailbox will be a Java object consisting of a data store to hold the message and access methods to write the message and withdraw it.

  1. Create the mailbox class that threads will use to deposit a message and remove it. It consists of an instance variable to store a message with access methods to assign a value to the string and to read and clear it. Write a class with a String instance variable and two access methods. The first one will assign a value to the variable. The second one will erase and return the variable.
  2. Create a thread class so that it deposits five times its name in the mailbox (writes its name in the string variable). Each thread will sleep a random time between each turn. You will pass the mailbox object to a thread as an argument of its constructor.
  3. Create a thread class that clears the mailbox (reads and empties the string variable) and prints the content on the screen. The thread must run – loop – infinitely. This thread will also sleep a random time between each turn.
  4. Write a main program that creates the mailbox, ten writer threads, one reader thread, and launches the threads.
  5. Observe the results and comment on them briefly.

Synchronizing Threads

In this exercise, you will coordinate threads so that no message is lost.

  1. Write new conditions in the mailbox access methods so that you are sure the threads will deposit and clear all the messages. Use the wait() and notifyAll() methods.
  2. Observe the results.

Programming: Server Integration

In the previous exercises, you have programmed a TCP server and a thread synchronization mechanism (a monitor). You will now integrate them so that they can function as a chat server.

  1. Determine which data are necessary to manage the chat participants. Design a class to represent them.
  2. Build a list mechanism, for instance using the Vector built-in class, to store the active participants. Observe that access to this data needs to be synchronized in order to guarantee that two threads does not try to update/read the data simultaneously.
  3. Integrate the monitor you developed in the previous part of the lab into the TCP server so that participants can connect using telnet. All the participants must receive the sequence of messages in the same order. Put all messages that should be broadcasted into the monitor and let a separate thread remove the messagess and broadcast them.
  4. You will use text-based commands: 'M: Content of the message' to send a message to all the participants, 'E: Content of the message' to echo the message to the user for testing purposes, and 'Q:' to disconnect. You may define other commands if you want.
  5. Be aware that participants can interrupt their session at any time.

Programming: Creating a Client

You have used telnet as the client of your server. You will now write your own TCP client in Java. The synopsis of the client command is java ChatClient machine port. The machine address will be either a domain name or dotted numbers. The program reads continuously command strings from the keyboard and sends them to a server identified by machine and port until the user stops it.

  1. Write the code that parses the command line.
  2. Use the Socket class to connect to the server.
  3. Write a loop that reads lines from the keyboard and, depending on your protocol, sends a string or the first character of the line to the server. Use the getInputStream() and getOutputStream() methods of the Socket class to obtain the socket streams.
  4. Make sure that your client can asynchronously send and receive messages. (Hint: use threads)