o7planning

Java DatagramChannel Tutorial with Examples

  1. DatagramChannel
  2. Example
  3. Static Factory methods
  4. Methods

1. DatagramChannel

The DatagramChannel is a class that represents an open connection to a network socket and uses the UDP/IP protocol to read or write data to the network.
public abstract class DatagramChannel
    extends AbstractSelectableChannel
    implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannel
UDP
User Datagram Protocol (UDP): In short, UDP is a protocol with rules for dividing data into small packets called Datagram(s) at the sender and rules for concatenating them together at the receiver. UDP is suitable for data transmission over the network in applications requiring low latency.
1 Datagram = 1 Gram of data. Datagram does not have quantitative meaning. Its size is not fixed and is only meant to be a very small data packet.
UDP/IP
The rules set by UDP are not enough to send data between 2 devices, so it needs to be combined with Internet Protocol (IP). And we have the UDP/IP protocol:
  • Internet Protocol (IP): Helps determine the location of devices on the network, and transport data packets over the Internet. Specifically in this case it will transport Datagram packets.
Packets sent over UDP/IP have no sequence information, and are not checked to see if they arrive as intended. With such a simple way of sending, UDP/IP is faster but less reliable than other protocols, such as TCP/IP. This speed makes a trade-off. If a data packet is lost in transit, it will not be resent. Therefore, applications that use UDP must be able to tolerate errors, loss, and duplication.
Technically, data loss is not a vulnerability in UDP. The cause of this is usually the quality of network infrastructure, network routers,...
Examples of a few types of services that commonly use UDP:
UDP is an ideal protocol for network applications that require low latency, such as in gaming, voice and video communications. These examples can suffer some data loss without adversely affecting perceived quality. In some cases, however, forward error correction techniques are used in addition to UDP to improve audio and video quality, despite some loss.
See more in-depth articles on UDP/IP and TCP/IP:
  • User Datagram Protocol - UDP
  • Transmission Control Protocol - TCP
The hierarchy of classes and interfaces is related to the DatagramChannel class:

2. Example

In this example, we will send a message between 2 programs running on 2 different computers. Here is an illustration of the example:
ReceiverProgram: The receiving program needs to open a DatagramChannel and listen at its IP address with a certain port, for example, "localhost:9999".
ReceiverProgram.java
package org.o7planning.datagramchannel.ex;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class ReceiverProgram {

    public static DatagramChannel startReceiver() throws IOException {
        DatagramChannel receiver = DatagramChannel.open();
        // Listening SocketAddress
        InetSocketAddress address = new InetSocketAddress("localhost", 9999);
        receiver.bind(address); // The receiver is listening at localhost:9999

        System.out.println("Receiver started at #" + address);
        return receiver;
    }

    public static String receiveMessage(DatagramChannel receiver) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        SocketAddress senderAddress = receiver.receive(buffer);
        String message = extractMessage(buffer);
        System.out.println("Received message from sender: " + senderAddress);
        return message;
    }

    private static String extractMessage(ByteBuffer buffer) {
        buffer.flip();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        String msg = new String(bytes);
        return msg;
    }

    public static void main(String[] args) throws IOException {
        DatagramChannel receiver = startReceiver();
        while (true) {
            String message = receiveMessage(receiver);
            System.out.println(" - Message: " + message);
            if("Bye!".equals(message)) {
                break;
            }
        }
        receiver.close();
        System.out.println("Receiver closed!");
    }
}
SenderProgram: The sending program (message) needs to open a DatagramChannel and send the message to the listening address of the receiving program (ReceiverProgram).
SenderProgram.java
package org.o7planning.datagramchannel.ex;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class SenderProgram {

    public static DatagramChannel startSender() throws IOException {
        DatagramChannel sender = DatagramChannel.open();
        // SocketAddress
        SocketAddress address = null;
        sender.bind(address);

        sender.configureBlocking(false);
        return sender;
    }
    public static void sendMessage(DatagramChannel sender, String msg, //
            SocketAddress receiverAddress) throws IOException {
        ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
        sender.send(buffer, receiverAddress);
    }
    public static void main(String[] args) throws IOException, InterruptedException {
        DatagramChannel sender = startSender();

        String[] messages = new String[] { "Hello", "How are you?", "Bye!" };
        // SocketAddress of the Receiver.
        InetSocketAddress receiverAddress = new InetSocketAddress("localhost", 9999);

        for (String message : messages) {
            // Send message to the Receiver!
            sendMessage(sender, message, receiverAddress);
            Thread.sleep(2 * 1000); // 2 seconds.
        }
        sender.close();
    }
}
To test the application, you need to run the ReceiverProgram class first, then run the SenderProgram class:
Output:
Receiver started at #localhost/127.0.0.1:9999
Received message from sender: /127.0.0.1:58179
 - Message: Hello
Received message from sender: /127.0.0.1:58179
 - Message: How are you?
Received message from sender: /127.0.0.1:58179
 - Message: Bye!
Receiver closed!

3. Static Factory methods

Static factory methods:
public static DatagramChannel open() throws IOException  
public static DatagramChannel open(ProtocolFamily family) throws IOException

4. Methods

public abstract class DatagramChannel
    extends AbstractSelectableChannel
    implements ByteChannel, ScatteringByteChannel, GatheringByteChannel, MulticastChannel
Methods that are inherited from ReadableByteChannel and WriteableChannel interfaces:
public abstract int read(ByteBuffer dst) throws IOException;  
public abstract int write(ByteBuffer src) throws IOException;
Methods that are inherited from the ScatteringByteChannel and GatheringByteChannel interfaces:
public abstract long read(ByteBuffer[] dsts, int offset, int length) throws IOException;  
public final long read(ByteBuffer[] dsts) throws IOException  

public abstract long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
public final long write(ByteBuffer[] srcs) throws IOException
Methods that are inherited from the SelectableChannel interface:
public final int validOps()
  • Java SelectableChannel
Methods inherited from the NetworkChannel and MulticastChannel interfaces:
public abstract SocketAddress getLocalAddress() throws IOException;
public abstract DatagramChannel bind(SocketAddress local) throws IOException;
public abstract <T> DatagramChannel setOption(SocketOption<T> name, T value) throws IOException;

MembershipKey join(InetAddress group, NetworkInterface interf) throws IOException;
MembershipKey join(InetAddress group, NetworkInterface interf, InetAddress source) throws IOException;
  • NetworkChannel
  • MulticastChannel
Other methods:
public abstract DatagramSocket socket();
public abstract boolean isConnected();
public abstract DatagramChannel connect(SocketAddress remote) throws IOException;
public abstract DatagramChannel disconnect() throws IOException;
public abstract SocketAddress getRemoteAddress() throws IOException;
public abstract SocketAddress receive(ByteBuffer dst) throws IOException;
public abstract int send(ByteBuffer src, SocketAddress target) throws IOException;