title: Java Get MulticastSocket.receive to Throw ClosedByInterruptException
body: <p>I have some code that reads data from a multicast socket until a user-defined end time.  I would also like to stop reading data if the thread is interrupted via a call to <code>Thread.interrupt</code> (or by any other user-initiated action you can come up with).  I can't figure out how to get notification when the thread is interrupted.  The existing code is as follows:</p>
  
  <pre><code>// 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
  } ...
  </code></pre>
  
  <p>I saw that there was a <code>DatagramSocket.getChannel</code> method that returns a <code>DatagramChannel</code>, so I naturally assumed that type was used to read/write to the underlying socket.  That assumption was incorrect, which means that <code>MulticastSocket</code> doesn't implement <code>InterruptibleChannel</code>.  Because of this, <code>MulticastSocket.receive</code> never throws a <code>ClosedByInterruptException</code>.</p>
  
  <p>I have searched online for examples, but can't figure out how to modify the above code to use a <code>DatagramChannel</code> instead of a <code>MulticastSocket</code>.  The problems I need help with are:</p>
  
  <ol>
  <li>How do I set the SO_TIMEOUT parameter on a DatagramChannel?</li>
  <li>How do I convert an <code>InetAddress</code> into a <code>NetworkInterface</code> object?</li>
  </ol>
  
  <p>The following is my best guess on how to convert my implementation from <code>MulticastSocket</code> to <code>DatagramChannel</code> to meet my requirements:</p>
  
  <pre><code>// 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);
  } ...
  </code></pre>
  
  <p>Will this approach even work?  <code>DatagramChannel.receive</code> doesn't list <code>SocketTimeoutException</code> as one of the exceptions it is able to throw.  If this will work, then please let me know how I need to change the second implementation to be equivalent to the first, but with the ability to throw a <code>ClosedByInterruptException</code> when a client calls <code>Thread.interrupt</code>.  If not, then does anyone have any other ideas as to how I can meet the requirement of stopping datagram reception at a pre-defined time, while also providing a way to stop execution via user interaction?</p>