Non-blocking TCP

Client in non-blocking mode

In this exercise we implement a client for the protocol Chaton in non-blocking mode.

Chaton Protocol

In this protocol, a message packet is made out of a login and a text in the following format:

+------------------+------------+------------------+------------+
| Login size (INT) | Login UTF8 | Text  size (INT) | Texte UTF8 |
+------------------+------------+------------------+------------+

The packets should not exceed 1024 bytes.

When a message packet is received by the server, it will broadcast it to all of the clients.

We propose the following code ClientChat.java to start your work. In this draft code, the input from the keyboard is read in the thread console and the selection loop is executed by the thread main. Warning, this means that you must use a thread-safe mechanism to communicate between the two.

In our proposed draft, the communication between these two thread is done by the methods sendCommand(String msg) and processCommands() that you are to implement.
  • A solution would be to use a BlockingQueue, but one must be careful, as we are not in the case of a producer-consumer in the strict sense.
  • The simplest (maybe) solution would be to synchronize these exchanges.
  • But probably, the cleanest solution would be to prepare a thread-safe class for this part.

Write a non-blocking client for the Chaton protocol.

Interactive console

We wish to add now a console input for our non-blocking server. More precisely, we would like to allow for the possibility of reading commands from the keyboard.

Your console should recognize the following commands:

Add an interactive console to your ServerEcho, making a new class ServerEchoWithConsole.

As we have seen during the lectures, the keys of the selector cannot be modified by a thread other than the one executing the selection loop. You must then, as for the client of the previous exercise, pay particular attention to the communication between the thread reading the keyboard input and the one controlling the selector.

You can test your server with the client ClientEchoSlow.jar and/or with the command netcat. Attention, when the communication with the jar is interrupted, the message "Sender thread killed by IOException ..." appears but its execution continues. This is completely normal.

(Optional) Console and removal of inactive clients

This time we want our non-blocking server to close down the connections with inactive clients.

Add to your code in ServerEchoWithConsole the removal of inactive clients, making a new class ServerEchoWithConsoleAndTimeout

It is not necessary to add more threads! A quick solution consists in adding a boolean field activeSinceLastTimeoutCheck to each Context. This boolean is true initially, and it is set to true each time a call to the methods doRead or doWrite is made. In the selection loop, we will, every TIMEOUT milliseconds, loop over the contexts associated to the connected clients and close down those for which the boolean is false. For all of the clients that are still connected we set the boolean to false.
In this way, if the context associated to a client sees no activity (no calls to doRead or doWrite) between to consecutive checks, it will be disconnected. As the checks occur (make sure of this) at least every TIMEOUT milliseconds, the disconnected clients have been inactive for at least this time.
It is important to recall that the method select is blocking. In order to make sure that we do not stay blocked for more than TIMEOUT millisecond, use the version of the method select with timeout.

  selector.select(this::treatKey,TIMEOUT);