UDP Servers

Basic principles of UDP server (1/2)

Unlike a client, the DatagramChannel of a server must be bound to a given port (clients need to know this port)

              dc.bind(new InetSocketAddress(7777));

Binds the datagram channel to the port 7777 (if available)

  • Raises a BindException if port 7777 is in already use.
    It is not possible to free/release such a port from Java; the server bounded to this port must be stopped.
  • Method bind accepts an InetSocketAddress...
    why not just a port number?

Basic principles of UDP server (2/2)

A server always responds to client's requests. It waits for solicitations and never initiates communication.
Thus, it simply loops like:

  • reveive a request from a client
  • compute/build a response
  • send the response to the client

Echo Server

ByteBuffer buff = ByteBuffer.allocateDirect(BUFFER_SIZE);

while (!Thread.interrupted()) {
    buff.clear();
    InetSocketAddress exp = (InetSocketAddress) dc.receive(buff);
    buff.flip();
    logger.info("Received " + buff.remaining() + " bytes from " + exp.toString());

    // Echo processing = do nothing (just flip)
    
    logger.info("Sending " + buff.remaining() + " bytes to " + exp.toString());
    dc.send(buff, exp);
}

Stateless vs stateful protocols

A protocol is stateless if the response to a given request of a client only depends on this request (and not on previous ones).

All protocols we have seen so far (Echo, UpperCase, BetterUpperCase and IdUpperCase) were stateless.

A protocol is stateful if the response to a request of a client depends on previous requests of this client (or others).

An example of stateful protocol

In the protocol Count, the server answers to any request with a packet containing a long in BigEndian representing the total number of request received from this client since server startup.

Here, we define a client as the pair (IP address, port), i.e. InetSocketAddress

Stateful UDP server

For a stateful protocol, server has to memorize information (state) about packets received from each client.

Be careful not to mix up packets coming from different clients.

Server keeps information up to date in a hashmap Hashmap<InetSocketAddress,ClientData>
where ClientData is a class that stores required data.

Be careful to minimize the amount of stored data and implement mecanisms to free useless memory.

Example for Count server

final ByteBuffer buffRec = ByteBuffer.allocateDirect(BUFFER_SIZE);
final ByteBuffer buffSend = ByteBuffer.allocateDirect(Long.BYTES);
final HashMap<InetSocketAddress,Long> map = new HashMap<>();
             
while (!Thread.interrupted()) {
  buffRec.clear();
  InetSocketAddress exp = (InetSocketAddress) dc.receive(buffRec);
     
  var nb = map.merge(exp,1l,Long::sum);	
             
  buffSend.clear();
  buffSend.putLong(nb).flip();
  dc.send(buffSend,exp);
}