In this exercise we implement a client for the protocol Chaton in non-blocking mode.
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.
sendCommand(String msg)
and processCommands()
that you are to implement.
BlockingQueue
, but one must be careful, as we are not in the case of a producer-consumer in the strict sense.Write a non-blocking client for the Chaton protocol.
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
.
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.
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);