If you really need the message to be processed by all the clients, you need a multi-cast / broad-cast protocol. In this sense, as stated in a previous question (Does Java NIO support broadcast or multicast?), NIO2 Supports multi-cast and broad-cast but not using the DatagramChannel class. Instead you have the MultiCastChannel interface (you can find official documentation in http://javanio.info/filearea/nioserver/WhatsNewNIO2.pdf and an example in: How do I implement a multicast client in NIO.2?).
Regarding your code, it should look like:
NetworkInterface netInterface = NetworkInterface.getByName("em1");
InetAddress group = InetAddress.getByName("localhost");
// Reader 1
System.out.println("Create Reader 1");
DatagramChannel s1 = DatagramChannel.open(StandardProtocolFamily.INET);
s1.setOption(StandardSocketOptions.SO_REUSEADDR, true);
s1.bind(new InetSocketAddress(PORT));
s1.setOption(StandardSocketOptions.IP_MULTICAST_IF, netInterface);
// Reader 2
System.out.println("Create Reader 2");
DatagramChannel s2 = DatagramChannel.open(StandardProtocolFamily.INET);
s2.setOption(StandardSocketOptions.SO_REUSEADDR, true);
s2.bind(new InetSocketAddress(PORT));
s2.setOption(StandardSocketOptions.IP_MULTICAST_IF, netInterface);
Be aware that multi-cast / broad-cast must be supported by your underlying hardware stack. Otherwise, the join
method will throw an exception.
If you don't need the message to be processed by all the clients but rather you need any of them to process it without blocking the others, you can set the non-blocking socket option. Considering the code you provided, I add below a solution with non-blocking:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.charset.StandardCharsets;
public class Main {
private static final String HOST = "localhost";
private static final int PORT = 1234;
private static final String MESSAGE = "HelloWorld";
private static final int MESSAGE_SIZE = MESSAGE.length();
public static void main(String[] args) throws IOException {
// Reader 1
System.out.println("Create Reader 1");
DatagramChannel s1 = DatagramChannel.open();
s1.configureBlocking(false);
s1.setOption(StandardSocketOptions.SO_REUSEADDR, true);
s1.bind(new InetSocketAddress(HOST, PORT));
// Reader 2
System.out.println("Create Reader 2");
DatagramChannel s2 = DatagramChannel.open();
s2.configureBlocking(false);
s2.setOption(StandardSocketOptions.SO_REUSEADDR, true);
s2.bind(new InetSocketAddress(HOST, PORT));
// Writer
System.out.println("Create Writer");
DatagramChannel s3 = DatagramChannel.open();
// Send and receive messages
System.out.println("Send message");
send(s3);
System.out.println("Receive message on Reader 1");
receive(s1);
System.out.println("Receive message on Reader 2");
receive(s2);
// Close
System.out.println("Close");
s1.close();
s2.close();
s3.close();
}
private static void send(DatagramChannel channel) throws IOException {
ByteBuffer buf = ByteBuffer.allocate(MESSAGE_SIZE);
buf.clear();
buf.put(MESSAGE.getBytes());
buf.flip();
int bytesSent = channel.send(buf, new InetSocketAddress(HOST, PORT));
System.out.println("Sent: " + bytesSent);
}
private static void receive(DatagramChannel channel) throws IOException {
ByteBuffer buf = ByteBuffer.allocate(MESSAGE_SIZE);
buf.clear();
channel.receive(buf);
String str = new String(buf.array(), StandardCharsets.UTF_8);
System.out.println("Received: " + str);
}
}
Which output is:
Create Reader 1
Create Reader 2
Create Writer
Send message
Sent: 10
Receive message on Reader 1
Received:
Receive message on Reader 2
Received: HelloWorld
Close