UDP Servers

Uppercase server

The aim of this exercise is to write a server for the IdUpperCase protocol.

Protocol IdUpperCase
A request to the server has the format:
  • a long in BigEndian identifying the request,
  • the bytes of the string encoded in UTF-8.
The answer of the server has the same format using the id of the request. The packets exchanged in this protocol have a maximal size of 1024 bytes.

For the servers, we will no longer write everything in the main method. A server will be an object of the class ServerIdUpperCaseUDP:

You can use the following template as a starting point: ServerIdUpperCaseUDP.java

Write a class ServerIdUpperCaseUDP which takes as argument the port of the server.

Test your class with the client you have written in the previous session.

$ java fr.uge.net.udp.ServerIdUpperCaseUDP 4545

If you still have not finished your client, you can use this client ClientIdUpperCaseUDP.jar.

Long sum server

The aim of this exercise is to write a service to perform sum of an arbitrary number of long integers. The client has a list of longs integers which he wants to sum. He will send each long in a different packet to the server. The server will sum the longs and send back the sum to the client.

This protocol is stateful and the server will need to store the informations received from the different clients (identified by the IP address + port number).

The protocol (we describe in detail below) is designed to handle several problems:

We now give a detailed presentation of the different packets involved in protocol. All the fields marked as long are signed eight bytes integers in BigEndian. Each packet will start by a byte coding its type. This byte is equal to:

Let us take the example of a client Charlie (C) who wants to send the longs (operands) 10000, 2000 and 300000 to a server called Serge (S) using our protocol. Charlie will use the session identifier 5555 for this sum.
Charlie will send his 3 operands, in 3 different packets:

+-----+-----------+-----------+-----------+-----------+
|  1  |   55555   |     0     |     3     |    10000  |  // C -> S OP 0
+-----+-----------+-----------+-----------+-----------+
   OP   sessionID   idPosOper   totalOper    opValue

+-----+-----------+-----------+-----------+-----------+
|  1  |   55555   |     1     |     3     |     2000  |  // C -> S OP 1
+-----+-----------+-----------+-----------+-----------+
   OP   sessionID   idPosOper   totalOper    opValue

+-----+-----------+-----------+-----------+-----------+
|  1  |   55555   |     2     |     3     |   300000  |  // C -> S OP 2
+-----+-----------+-----------+-----------+-----------+
   OP   sessionID   idPosOper   totalOper    opValue
Now assume that Serge only receives the packets 1 and 2 (the packet 0 is lost!); Serge will send back two acknowledge packets:
+-----+-----------+-----------+
|  2  |   55555   |     1     |  // S -> C ACK 1
+-----+-----------+-----------+
  ACK   sessionID   idPosOper  

+-----+-----------+-----------+
|  2  |   55555   |     2     |  // S -> C ACK 2
+-----+-----------+-----------+
  ACK   sessionID   idPosOper  
But the acknowledgement 2 is lost and Charlie only receives the acknowledgement for the packet 1. After a fixed delay, Charlie decides to send again the operand 0 and 2 for which he has not received an acknowledgement:
+-----+-----------+-----------+-----------+-----------+
|  1  |   55555   |     0     |     3     |    10000  |  // C -> S OP 0
+-----+-----------+-----------+-----------+-----------+
   OP   sessionID   idPosOper   totalOper    opValue

+-----+-----------+-----------+-----------+-----------+
|  1  |   55555   |     2     |     3     |   300000  |  // C -> S OP 2
+-----+-----------+-----------+-----------+-----------+
   OP   sessionID   idPosOper   totalOper    opValue
This time, Serge receives both packets, he only adds to the sum the first one because the second one was previously received and was already taken into account. Still he sends the acknowledgement packets for both packets:
+-----+-----------+-----------+
|  2  |   55555   |     0     |  // S -> C ACK 0
+-----+-----------+-----------+
  ACK   sessionID   idPosOper  

+-----+-----------+-----------+
|  2  |   55555   |     2     |  // S -> C ACK 2
+-----+-----------+-----------+
  ACK   sessionID   idPosOper  
furthermore, now that Serge has the 3 required operands (thanks to totalOper), he also send a packet giving the result of the sum.
+----+-----------+-----------+
|  3 | sessionID |   312400  |  // S -> C RES 312400
+----+-----------+-----------+
  RES  sessionID      sum
If Charlie receives both acknowledgements, he knows for sure that all operands are now known by Serge. But even if he does not receive the acknowledgment 0 (which might be lost), he can stop as soon as he receives the RES packet which contains the final answer.
However, if Charlie has received all the acknowledgments but not the RES packet (after some time), he can guess that the RES packet has been lost. He will need to send an OP packet for any operand to trigger the resent by Serge of the RES packet.

Write a server ServerLongSum for this protocol using the same template as in the previous exercise.

Test

To test that your server behaves correctly, you can use the following program ValidatorLongSumUDP.jar. This program tests your server by simulating several clients.

In three different terminals, simultaneously visible on screen, run the three programs:

    $ java fr.uge.net.udp.ServerLongSumUDP 7777
    $ java -jar UDPProxy.jar 6666 localhost 7777
    $ java -jar ValidatorLongSumUDP.jar localhost 6666

If everything is correct, you should see:

    Trying 5 queries one after the other.
    Query 1 succeeded!
    Query 2 succeeded!
    Query 3 succeeded!
    Query 4 succeeded!
    Query 5 succeeded!
    Trying 5 queries from the same client at the same time.
    Test passed
    Trying 5 clients at the same time.
    Test passed

Freeing ressources on the server

Currently your server stores in a HashMap all the data of all the sums it ever performed. In the long run, this will pose a memory problem.

What ressources can be freed when the RES packet is sent ? Is it possible to remove all the informations related to this sum from the HashMap of the server.

A first possible solution to help the server free its ressources consists in modifying the protocol to allow the client to signal that the server can free the ressources corresponding to a sum. For this, we need to introduce two new packet types.

Modify your server to handle this extended protocol.

To test your server, you can use the following progam ClientFreeLongSum.jar. This program tests your server by simulating several clients.

In 3 different terminals (on the same screen), launch the 3 programs below:

    $ java fr.uge.net.udp.ServerFreeLongSumUDP 7777
    $ java -jar UDPProxy.jar 6666 localhost 7777
    $ java -jar ClientFreeLongSumUDP.jar localhost 6666

This modification is not sufficient because it assumes that the client respects the protocol. It would be easy for someone to start a lot of sums on your server and never send any CLEAN packet. We need a mechanism to deal with this ill-intentionned clients. The solution is to give a time limit for each sum. In other terms, if no packet concerning a given sum are received over a given period of time (for instance 5 minutes) then this sum can be discarded by the server.

Implement this mecanism on your server.