We now consider the protocol IdUpperCase
where each request is prefixed with a id (a long in BigEndian). The id of the request is used to prefix the answer to this request.
IdUpperCase
long
in BigEndian identifying the request,
UTF-8
.
We provide a server
ServerIdUpperCase.jar
which implements the protocol IdUpperCase
. You can reuse the UDP proxy UDPProxy.jar.
$ java -jar ServerIdUpperCaseUDP.jar 4545 UTF-8 $ java -jar UDPProxy.jar 7777 localhost 4545 -no-swap
Starting from the template ClientIdUpperCaseUDPOneByOne.java, write a program ClientIdUpperCaseUDPOneByOne
to uppercase all the lines of a file using a server.
Your client must send the lines one by one. For instance, if the file contains two lines. The client will first send a request corresponding to the first line with the id 0. If no answer is received with the id 0 before
timeout
milliseconds, the client will send the request again. This process is repeated until an answer with id 0 is received.
Then client moves on the second line using id 1.
As in the previous exercise, the class ClientIdUpperCaseUDPOneByOne.java
takes as parameters the two files in-filename
and out-filename
, the timeout in milliseconds timeout
and the address of the server
IdUpperCase
(hostname
port
).
You can test your class with the file in.txt using the following line:
$ java fr.uge.net.udp.ClientIdUpperCaseUDPOneByOne in.txt out.txt 300 localhost 7777
Remember to launch the server and UDP proxy as shown above.
Check that your client to not resend the request sooner than timeout
millisecondes. This can happen if when you receive an answer with the wrong id, you resend immedialty without checking how much time as ellapsed since the last send.
To help you perform this verification, we provide a fake server ServerIdUpperCaseTestTimeout.jar. This server does not respond to request normally. Every 100 milliseconds, it sends an answer with the id -1. Furthermore it prints the time ellapsed between two receive.
Test your program with the following setup:
$ java -jar ServerIdUpperCaseUDPTestTimeout.jar 7777 $ java fr.uge.net.udp.ClientIdUpperCaseUDPOneByOne in.txt out.txt 300 localhost 7777If your client respect the timeout, you should see times very close to the timeout timeout.
Time since last receive: 301 ms Time since last receive: 301 ms Time since last receive: 301 ms Time since last receive: 301 ms Time since last receive: 300 ms Time since last receive: 301 ms ....
The one by one method seen in the previous example is quite slow. Indeed, every time a packet is lost, we have to wait timeout
milliseconds before resending it.
A faster approach consists in sending all the requests (with different ids) at the same time. Then during timeout
milliseconds, we receive all the answers from the server and store them. After timeout
milliseconds, we send again all the request for which we did not receive an answer. And so on, until all the answers have been received.
Starting from the template ClientIdUpperCaseUDPBurst.java, write a client ClientIdUpperCaseUDPBurst
.
This class takes the same parameters as the class ClientIdUpperCaseUDPOneByOne
.
You can use a
java.util.BitSet
to keep track of which lines have been received.
The main
will perform the following tasks:
BitSet
;
timeout
milliseconds
all the requests for the line that have not yet been received. Contrarily to the one by one case,
its is easier to have the main
perform the receive operations;
BitSet
. When all the answers have been received,
the lines are written to the output file. You have to take into account that the BitSet
is accessed concurrently by two threads. You will need a lock to protect
the access to the BitSet
. The best practice is to design a threadsafe class that contains the BitSet
.
You can test your class with the file in.txt as follows:
$ java -jar ServerIdUpperCaseUDP.jar 4545 UTF-8 $ java -jar UDPProxy.jar 7777 localhost 4545 -no-swap $ java fr.uge.net.udp.ClientIdUpperCaseUDPBurst in.txt out.txt 300 localhost 7777
Do not forget to launch the server and proxy.