Non-blocking UDP

Echo non-blocking server

The exercise aims to implement non-blocking concepts in UDP as seen in the lecture. We want to code a non-blocking server for the Echo protocol.

Echo protocol
In the Echo protocol, server sends back datagrams to clients with the same data as received. We assume that packets never exceed 1024 bytes of data.

Starting from the file ServerEcho.java, write a server ServerEchoNonBlocking that accepts as argument its listening port.

Warning: recall that even when the selector provides a selection key corresponding to the possibility to send or receive, there is no garanty that a call to datagramChannel.send() or datagramChannel.receive() will actually send or revceive something.

  • You can verify that a packet has been received by testing the address returned by datagramChannel.receive(): it is null if no packet has been received.
  • You can verify that a packet has been by testing buff.hasRemaining() after the call to datagramChannel.send(buff,exp): if sending fails the working zone of buff is unchanged.

If sending or receiving have not been performed, your code must ask the selector (again) for a new key before a new attempt.

The situation where a selector propose a key allowing an operation, that finally cannot be performed. Thus you will not be able to test your code against these cases; you must then plan to manage your code to deal with these situations in case of failing receive or send.

To test your server, you can use the NetcatUDP.jar client, that sends packets for each line read from the keyborad (UTF8 encoded) and prints the string corresponding to the response (UTF8 decoded).

$ java fr.uge.net.udp.nonblocking.ServerEcho 4545
$ java -jar NetcatUDP.jar localhost 4545 UTF8
toto
String: toto

We will now sligthly modifiy the Echo protocol to obtain the EchoPlus protocol:

EchoPlus protocol
In this protocol, the server no longer sends back packets identical packets as received but sends a packet in which every byte has been incremented by 1 modulo 256.

All packets are assumed to contain at most 1024 bytes.

For example, upon receiving the following 7-bytes packet:

    +----------------------+
    | FF 0A 11 1F FF 00 01 |
    +----------------------+
the server will send back to the client the following packet:
    +----------------------+
    | 00 0B 12 20 00 01 02 |
    +----------------------+

Write a class ServerEchoPlus implementing in non-blocking mode a server for the EchoPlus protocol.
You can start from your ServerEcho class.

Carefully check that your code is correct even when datagramChannel.send() or datagramChannel.receive() do not send or receive anything (despite being selected by the selector).

To test your server, you can use the client NetcatUDP.jar.

$ java fr.uge.net.udp.nonblocking.ServerEchoPlus 4545
$ java -jar NetcatUDP.jar localhost 4545 UTF8
toto
Received 4 bytes from /127.0.0.1:4545
String: upup

Multi-port Echo NIO Server

In this exercise, we want to write a Echo server ServerEchoMultiPort which takes as argument a range of port (an not a single port as in Exercise 1). Starting the server with the following parameters:

java fr.uge.udp.nonblocking.ServerEchoMultiPort 7000 7100
will allow to have the behavior of as many servers on each port in the interval [7000..7100] (inclusive).

Note that with blocking IO, the only way to implement such a server is to use at least a new thread for each listening port... we will see that a unique thread is sufficient with non-blocking IO.

In our exercises until now, the selector only monitored a single DatagramChannel. Here, we have to create a DatagramChannel for each listening port and register all of them in the same selector.

For each SelectionKey that stands for such a registration, we need to store a ByteBuffer (data) and a InetSocketAddress (client). You will gather these two information in a inner class Context.

To associate such a Context object to a given SelectionKey, we would normally use a HashMap<SelectionKey,Context>. However, it is not necessary since the class SelectionKey already provides a method selectionKey.attach(Object obj) allowing us to store any object associated with the key; method selectionKey.attachment() retrieves this object.

Note that it is possible to "attach" an object to the key as soon as the DatagramChannel is registered with the selector (the key is generated by this registration):

    dc.register(selector, SelectionKey.OP_READ, new Context());

You can test your server starting the ClientTestEchoMultiPort.jar client as follows:

java -jar ClientTestEchoMultiPort.jar localhost 7000 7100
This test simulates 10 clients sending 10 packets to the range of ports between 7000 et 7100, and checks that all corresponding responses are received. You should see:
No error found.