Skip to content

Instantly share code, notes, and snippets.

@kazimsarikaya
Created January 22, 2015 12:13
Show Gist options
  • Save kazimsarikaya/4ad079cfcb87a5155b27 to your computer and use it in GitHub Desktop.
Save kazimsarikaya/4ad079cfcb87a5155b27 to your computer and use it in GitHub Desktop.
java multicast with nio and selector suppor
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.StandardProtocolFamily;
import java.net.StandardSocketOptions;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author kazim sarikaya
*/
public class MulticastExample {
private static boolean cont = true;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
int type = 3;
if (args.length == 1) {
switch (args[0]) {
case "r":
type = 1;
break;
case "w":
type = 2;
break;
case "rw":
type = 3;
break;
}
}
InetAddress group = InetAddress.getByName("239.1.2.3");
int port = 5000;
final InetSocketAddress target = new InetSocketAddress(group, port);
NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName("192.168.56.1"));
DatagramChannel datagramChannel = DatagramChannel.open(StandardProtocolFamily.INET)
.setOption(StandardSocketOptions.SO_REUSEADDR, true)
.bind(new InetSocketAddress(port))
.setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);
datagramChannel.configureBlocking(false);
datagramChannel.join(group, ni);
final AtomicInteger rcnt = new AtomicInteger(0);
final AtomicInteger wcnt = new AtomicInteger(0);
Thread reader = null;
if (type == 1 || type == 3) {
final Selector selector_read = Selector.open();
datagramChannel.register(selector_read, SelectionKey.OP_READ);
reader = new Thread() {
@Override
public void run() {
try {
ByteBuffer bb = ByteBuffer.allocate(100);
while (cont) {
selector_read.select();
Iterator<SelectionKey> iterator = selector_read.selectedKeys().iterator();
while (iterator.hasNext()) {
if(!cont){
break;
}
SelectionKey key = iterator.next();
if (key.isReadable()) {
DatagramChannel dc = (DatagramChannel) key.channel();
dc.receive(bb);
bb.flip();
byte[] data = new byte[bb.limit()];
bb.get(data);
if (new String(data, "utf-8").equals("hello world")) {
rcnt.incrementAndGet();
}
bb.clear();
iterator.remove();
}
}
}
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(ReceiverApp.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ReceiverApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
reader.setName("reader");
reader.start();
}
Thread writer = null;
if (type == 2 || type == 3) {
final Selector selector_write = Selector.open();
datagramChannel.register(selector_write, SelectionKey.OP_WRITE);
writer = new Thread() {
@Override
public void run() {
try {
ByteBuffer bb = ByteBuffer.wrap("hello world".getBytes("utf-8"));
while (cont) {
selector_write.select();
Iterator<SelectionKey> iterator = selector_write.selectedKeys().iterator();
while (iterator.hasNext()) {
if(!cont){
break;
}
SelectionKey key = iterator.next();
if (key.isWritable()) {
DatagramChannel dc = (DatagramChannel) key.channel();
if (dc.send(bb, target) == "hello world".length()) {
wcnt.incrementAndGet();
}
bb.flip();
iterator.remove();
}
}
}
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(ReceiverApp.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ReceiverApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
writer.setName("writer");
writer.start();
}
Scanner readline = new Scanner(System.in);
readline.nextLine();
cont = false;
if (type == 1 || type == 3) {
reader.interrupt();
}
if (type == 2 || type == 3) {
writer.interrupt();
}
System.out.println("rcnt: " + rcnt.get() + " wcnt: " + wcnt.get());
} catch (UnknownHostException ex) {
Logger.getLogger(ReceiverApp.class.getName()).log(Level.SEVERE, null, ex);
} catch (SocketException ex) {
Logger.getLogger(ReceiverApp.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ReceiverApp.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@QIvan
Copy link

QIvan commented Apr 26, 2018

Thank you for this gist!

@QIvan
Copy link

QIvan commented Apr 26, 2018

I've found a workaround how to not hardcode a NetworkInterface like here

NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName("192.168.56.1"));

you can use instead this code

final NetworkInterface networkInterface;
try (MulticastSocket temp = new MulticastSocket()) {
    networkInterface = temp.getNetworkInterface();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment