UDP Basics in Java

Lecture 02

The UDP protocol

The UDP protocol is similar to the postal services.

  • socket UDP = mailbox
  • IP address + port number = postal address
  • UDP packet = parcel/letter
  • A UDP socket allows to send and receive packets from/to any other reachable UDP socket.

    There is no notion of connection!

    Principe UDP

    User Datagram Protocol (RFC 768)

    Guaranties of UDP

  • Packets can be lost.
  • Sending order and receiving order of packets may differ.
  • If a packet arrives, it is not modified (data integrity).
  • If you send P1 and then P2 to the same adress. The target may receive P1 and then P2 or P2 and then P1 or only P1 or only P2 or nothing.

    IP in Java

    Java provides a very limited access to IP protocol:


  • IP Address
  • Socket Address
  • IP Address

  • IPv4 (4 bytes): 192.168.0.1
  • IPv6 (16 bytes): FE80:0000:0000:0000:0202:B3FF:FE1E:8329
  • Represented in Java by InetAddress with two sub-classes Inet4Address and Inet6Address.

    We will always work with InetAddress.

    InetAddress

    Created using the factory method InetAddress.getByName(String host).

    InetAddress addr1 = InetAddress.getByName("192.168.0.1");
    InetAddress addr2 = InetAddress.getByName("FE80:0:0:0:0202:B3FF:FE1E:8329");
    InetAddress addr3 = InetAddress.getByName("www.google.fr");
                                        
    System.out.println(addr1+"\n"+addr2+"\n"+addr3);
    
    /192.168.0.1
    /fe80:0:0:0:202:b3ff:fe1e:8329
    www.google.fr/64.233.166.94
    

    This third example requires a DNS resolution.

    InetAddress = address (numerical) + [ name ]

    InetSocketAddress

    Socket Address = IP Address + port number

    Several constructors:

    InetAddress inetAddress = InetAddress.getByName("www.google.com");
    InetSocketAddress insa1 = new InetSocketAddress(inetAddress,7);
                                        
    InetSocketAddress insa2 = new  InetSocketAddress("www.u-pem.fr",7);
    
    InetSocketAddress insa3 = new InetSocketAddress("192.168.0.1",1025);
    
    InetSocketAddress insa4 = new  InetSocketAddress(7777);
    
    System.out.println(insa1+"\n"+insa2+"\n"+insa3+"\n"+insa4);
    
    www.google.com/173.194.67.147:7
    www.u-pem.fr/193.50.159.151:7
    /192.168.0.1:1025
    0.0.0.0/0.0.0.0:7777
    

    DatagramChannel

    UDP sockets are represented by the class DatagramChannel.

    They are created using the factory method:
    DatagramChannel.open

    DatagramChannel dc = DatagramChannel.open();
    

    Not yet bound (no bind) = no socket address

    DatagramChannel

    Binding is done using datagramChannel.bind.

    dc.bind(null);
    

    Binds to a random available port

    Sending a packet

    To send a packet, we need data (ByteBuffer in read-mode) and socket address of the recipient (InetSocketAddress)

    We use the method send of DatagramChannel:

    datagramChannel.send(ByteBuffer buff, SocketAddress dest);

    This method is blocking: it returns when buff.remaining() data have been flushed to the system (to be sent).

    DatagramChannel dc; 
    ...
    ByteBuffer buff = StandardCharsets.UTF_8.encode("Hello world €");
    InetSocketAddress dest= new InetSocketAddress("gaspard.univ-mlv.fr",7);
    dc.send(buff,dest);
    

    Receiving a packet

    To receive a packet, we need a ByteBuffer ready to store incoming data (write-mode).

    SocketAddress datagramChannel.receive(ByteBuffer buff);

    This method is blocking: it returns when data of a packet has been read and stored into buff.
    The method will return the socket address of the sender.

    DatagramChannel dc;
    ...
    ByteBuffer buff = ByteBuffer.allocate(1024);
    InetSocketAddress exp=(InetSocketAddress) dc.receive(buff);
    buff.flip();
    System.out.println("Received "+ buff.remaining() + " bytes from "+ exp);
    

    Don't forget the flip !

    If the packet size is greater than the the buffer size, the extra data is lost without any notification.

    Focus on the client side (0/11)

    Focus on the client side (1/11)

    Focus on the client side (2/11)

    Focus on the client side (3/11)

    Focus on the client side (4/11)

    Focus on the client side (5/11)

    Focus on the client side (6/11)

    Focus on the client side (7/11)

    Focus on the client side (8/11)

    Focus on the client side (9/11)

    Focus on the client side (10/11)

    Focus on the client side (11/11)

    Freeing resources

    The creation with open and the binding with bind reserve system resources
    (descriptor, system buffers, port)

    You must free these resources

    either with datagramChannel.close();

    or with try-with-resources

    try(DatagramChannel dc = DatagramChannel.open()){
        ...
    }