Ich habe einige Code, der Daten von einem Multicast-Socket bis zu einer benutzerdefinierten Endzeit liest. Ich würde auch gerne aufhören, Daten zu lesen, wenn der Thread durch einen Anruf an Thread.interrupt
(oder durch eine andere vom Benutzer initiierte Aktion, die Sie auftauchen können) unterbrochen wird. Ich kann nicht herausfinden, wie man eine Benachrichtigung erhält, wenn der Thread unterbrochen wird. Der bestehende Code lautet wie folgt:Java Get MulticastSocket.Receive zu Throw ClosedByInterruptException
// These are the constants I am given
final int mcastPort = ...;
final InetAddress mcastIP = ...;
final InetAddress ifaceIP = ...; // Null indicates all interfaces should be used
final Instant endTime = ...; // Time at which to stop processing
// Initialize a datagram
final byte[] buffer = new byte[1000];
final DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// Process incoming datagram packets
try (final MulticastSocket socket = new MulticastSocket(port)) {
socket.joinGroup(mcastIP);
if (ifaceIP != null)
socket.setInterface(ifaceIP);
do {
final Duration soTimeout = Duration.between(Instant.now(), endTime);
socket.setSoTimeout(soTimeout);
socket.receive(packet);
// Process packet
...
} while (true);
} catch (final SocketTimeoutException e) {
// Normal condition... the recording time has ended
} catch (final ClosedByInterruptException e) {
// Uh-oh... this never happens
} ...
ich sah, dass es eine DatagramSocket.getChannel
Methode war, die ein DatagramChannel
zurückkehrt, so dass ich natürlich angenommen, dass Typ verwendet wurde/Schreiben in den zugrunde liegenden Socket zu lesen. Diese Annahme war falsch, was bedeutet, dass MulticastSocket
InterruptibleChannel
nicht implementiert. Aus diesem Grund wirft MulticastSocket.receive
nie eine ClosedByInterruptException
.
Ich habe online nach Beispielen gesucht, aber kann nicht herausfinden, wie Sie den obigen Code ändern, um eine DatagramChannel
anstelle von MulticastSocket
zu verwenden. Die Probleme, die ich brauche, sind:
- Wie setze ich den Parameter SO_TIMEOUT auf einem DatagramChannel?
- Wie konvertiere ich ein
InetAddress
in einNetworkInterface
Objekt?
Hier finden Sie meine beste Vermutung auf, wie meine Implementierung MulticastSocket
-DatagramChannel
konvertieren meine Anforderungen zu erfüllen:
// Initialize a buffer
final ByteBuffer buffer = ByteBuffer.allocate(1000);
try (final DatagramChannel mcastChannel = DatagramChannel.open()) {
mcastChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
mcastChannel.connect(new InetSocketAddress(port));
mcastChannel.join(mcastIP);
if (ifaceIP != null)
// HELP: this option requires an InterfaceAddress object,
// but I only have access to an InetAddress object
mcastChannel.setOption(StandardSocketOptions.IP_MULTICAST_IF, ifaceIP);
do {
final Duration soTimeout = Duration.between(Instant.now(), endTime);
// HELP: SO_TIMEOUT is not a member of StandardSocketOptions
mcastChannel.setOption(SO_TIMEOUT, ???);
mcastChannel.receive(buffer);
// Process packet
...
} while (true);
} ...
Wird dieser Ansatz auch arbeiten? DatagramChannel.receive
listet SocketTimeoutException
nicht als eine der Ausnahmen auf, die es auslösen kann. Wenn dies funktioniert, lassen Sie mich bitte wissen, wie ich die zweite Implementierung ändern muss, um der ersten zu entsprechen, aber mit der Möglichkeit, eine ClosedByInterruptException
zu werfen, wenn ein Client Thread.interrupt
aufruft. Wenn nicht, hat dann jemand andere Ideen, wie ich die Anforderung erfüllen kann, den Datagramm-Empfang zu einem vordefinierten Zeitpunkt zu stoppen, während er auch eine Möglichkeit bietet, die Ausführung durch Benutzerinteraktion zu stoppen?
Verwenden Sie keine Angebotsformatierung für Text, der nicht zitiert wird. – EJP