2014-08-19 14:02:23 +03:00
|
|
|
/**
|
2017-01-04 17:37:10 +01:00
|
|
|
* Copyright (C) 2009-2017 Lightbend Inc. <http://www.lightbend.com>
|
2014-08-19 14:02:23 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package docs.io;
|
|
|
|
|
|
|
|
|
|
//#imports
|
|
|
|
|
import akka.actor.ActorRef;
|
|
|
|
|
import akka.actor.UntypedActor;
|
|
|
|
|
import akka.event.Logging;
|
|
|
|
|
import akka.event.LoggingAdapter;
|
|
|
|
|
import akka.io.Inet;
|
|
|
|
|
import akka.io.Udp;
|
|
|
|
|
import akka.io.UdpMessage;
|
|
|
|
|
import akka.util.ByteString;
|
|
|
|
|
|
|
|
|
|
import java.net.InetAddress;
|
|
|
|
|
import java.net.InetSocketAddress;
|
|
|
|
|
import java.net.NetworkInterface;
|
|
|
|
|
import java.net.StandardProtocolFamily;
|
2015-04-30 09:23:18 +02:00
|
|
|
import java.net.DatagramSocket;
|
2014-08-19 14:02:23 +03:00
|
|
|
import java.nio.channels.DatagramChannel;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
//#imports
|
|
|
|
|
|
|
|
|
|
public class JavaUdpMulticast {
|
|
|
|
|
//#inet6-protocol-family
|
|
|
|
|
public static class Inet6ProtocolFamily extends Inet.DatagramChannelCreator {
|
|
|
|
|
@Override
|
|
|
|
|
public DatagramChannel create() throws Exception {
|
|
|
|
|
return DatagramChannel.open(StandardProtocolFamily.INET6);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#inet6-protocol-family
|
|
|
|
|
|
|
|
|
|
//#multicast-group
|
2015-04-30 09:23:18 +02:00
|
|
|
public static class MulticastGroup extends Inet.AbstractSocketOptionV2 {
|
2014-08-19 14:02:23 +03:00
|
|
|
private String address;
|
|
|
|
|
private String interf;
|
|
|
|
|
|
|
|
|
|
public MulticastGroup(String address, String interf) {
|
|
|
|
|
this.address = address;
|
|
|
|
|
this.interf = interf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2015-04-30 09:23:18 +02:00
|
|
|
public void afterBind(DatagramSocket s) {
|
2014-08-19 14:02:23 +03:00
|
|
|
try {
|
|
|
|
|
InetAddress group = InetAddress.getByName(address);
|
|
|
|
|
NetworkInterface networkInterface = NetworkInterface.getByName(interf);
|
2015-04-30 09:23:18 +02:00
|
|
|
s.getChannel().join(group, networkInterface);
|
2014-08-19 14:02:23 +03:00
|
|
|
} catch (Exception ex) {
|
|
|
|
|
System.out.println("Unable to join multicast group.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#multicast-group
|
|
|
|
|
|
|
|
|
|
public static class Listener extends UntypedActor {
|
|
|
|
|
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
|
|
|
|
|
|
|
|
|
|
ActorRef sink;
|
|
|
|
|
|
|
|
|
|
public Listener(String iface, String group, Integer port, ActorRef sink) {
|
|
|
|
|
this.sink = sink;
|
|
|
|
|
|
|
|
|
|
//#bind
|
|
|
|
|
List<Inet.SocketOption> options = new ArrayList<>();
|
|
|
|
|
options.add(new Inet6ProtocolFamily());
|
|
|
|
|
options.add(new MulticastGroup(group, iface));
|
|
|
|
|
|
|
|
|
|
final ActorRef mgr = Udp.get(getContext().system()).getManager();
|
|
|
|
|
// listen for datagrams on this address
|
|
|
|
|
InetSocketAddress endpoint = new InetSocketAddress(port);
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
mgr.tell(UdpMessage.bind(self(), endpoint, options), self());
|
2014-08-19 14:02:23 +03:00
|
|
|
//#bind
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceive(Object msg) {
|
|
|
|
|
if (msg instanceof Udp.Bound) {
|
|
|
|
|
final Udp.Bound b = (Udp.Bound) msg;
|
2014-09-05 10:17:57 +02:00
|
|
|
log.info("Bound to {}", b.localAddress());
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
sink.tell(b, self());
|
2014-08-19 14:02:23 +03:00
|
|
|
} else if (msg instanceof Udp.Received) {
|
|
|
|
|
final Udp.Received r = (Udp.Received) msg;
|
2014-09-05 10:17:57 +02:00
|
|
|
final String txt = r.data().decodeString("utf-8");
|
|
|
|
|
log.info("Received '{}' from {}", txt, r.sender());
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
sink.tell(txt, self());
|
2014-08-19 14:02:23 +03:00
|
|
|
} else unhandled(msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static class Sender extends UntypedActor {
|
|
|
|
|
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
|
|
|
|
|
|
2014-09-05 10:17:57 +02:00
|
|
|
String iface;
|
2014-08-19 14:02:23 +03:00
|
|
|
String group;
|
|
|
|
|
Integer port;
|
|
|
|
|
String message;
|
|
|
|
|
|
2014-09-05 10:17:57 +02:00
|
|
|
public Sender(String iface, String group, Integer port, String msg) {
|
|
|
|
|
this.iface = iface;
|
2014-08-19 14:02:23 +03:00
|
|
|
this.group = group;
|
|
|
|
|
this.port = port;
|
|
|
|
|
this.message = msg;
|
|
|
|
|
|
|
|
|
|
List<Inet.SocketOption> options = new ArrayList<>();
|
|
|
|
|
options.add(new Inet6ProtocolFamily());
|
|
|
|
|
|
|
|
|
|
final ActorRef mgr = Udp.get(getContext().system()).getManager();
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
mgr.tell(UdpMessage.simpleSender(options), self());
|
2014-08-19 14:02:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceive(Object msg) {
|
|
|
|
|
if (msg instanceof Udp.SimpleSenderReady) {
|
2014-09-05 10:17:57 +02:00
|
|
|
InetSocketAddress remote = new InetSocketAddress(group + "%" + iface, port);
|
2014-08-19 14:02:23 +03:00
|
|
|
log.info("Sending message to " + remote);
|
improve AbstractActor, #21717
* Receive class that wraps PartialFunction, to avoid
scary scala types
* move AbstractActorContext to AbstractActor.ActorContext
* converting docs, many, many UntypedActor
* removing UntypedActor docs
* add unit test for ReceiveBuilder
* MiMa filters
* consistent use of getContext(), self(), sender()
* rename cross references
* migration guide
* skip samples for now
* improve match type safetyi, add matchUnchecked
* the `? extends P` caused code like this to compile:
`match(String.class, (Integer i) -> {})`
* added matchUnchecked, since it can still be useful (um, convenient)
to be able to do:
`matchUnchecked(List.class, (List<String> list) -> {})`
* eleminate some scala.Option
* preRestart
* findChild
* ActorIdentity.getActorRef
2016-12-13 10:59:29 +01:00
|
|
|
sender().tell(UdpMessage.send(ByteString.fromString(message), remote), self());
|
2014-08-19 14:02:23 +03:00
|
|
|
} else unhandled(msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|