@Test
  public void verifySendMulticastWithAcks() throws Exception {

    MulticastSocket socket;
    try {
      socket = new MulticastSocket();
    } catch (Exception e) {
      return;
    }
    final int testPort = socket.getLocalPort();
    final AtomicInteger ackPort = new AtomicInteger();

    final String multicastAddress = "225.6.7.8";
    final String payload = "foobar";
    final CountDownLatch listening = new CountDownLatch(2);
    final CountDownLatch ackListening = new CountDownLatch(1);
    final CountDownLatch ackSent = new CountDownLatch(2);
    Runnable catcher =
        new Runnable() {
          @Override
          public void run() {
            try {
              byte[] buffer = new byte[1000];
              DatagramPacket receivedPacket = new DatagramPacket(buffer, buffer.length);
              MulticastSocket socket = new MulticastSocket(testPort);
              socket.setInterface(InetAddress.getByName(multicastRule.getNic()));
              socket.setSoTimeout(8000);
              InetAddress group = InetAddress.getByName(multicastAddress);
              socket.joinGroup(group);
              listening.countDown();
              assertTrue(ackListening.await(10, TimeUnit.SECONDS));
              LogFactory.getLog(getClass())
                  .debug(Thread.currentThread().getName() + " waiting for packet");
              socket.receive(receivedPacket);
              socket.close();
              byte[] src = receivedPacket.getData();
              int length = receivedPacket.getLength();
              int offset = receivedPacket.getOffset();
              byte[] dest = new byte[6];
              System.arraycopy(src, offset + length - 6, dest, 0, 6);
              assertEquals(payload, new String(dest));
              LogFactory.getLog(getClass())
                  .debug(Thread.currentThread().getName() + " received packet");
              DatagramPacketMessageMapper mapper = new DatagramPacketMessageMapper();
              mapper.setAcknowledge(true);
              mapper.setLengthCheck(true);
              Message<byte[]> message = mapper.toMessage(receivedPacket);
              Object id = message.getHeaders().get(IpHeaders.ACK_ID);
              byte[] ack = id.toString().getBytes();
              DatagramPacket ackPack =
                  new DatagramPacket(
                      ack,
                      ack.length,
                      new InetSocketAddress(multicastRule.getNic(), ackPort.get()));
              DatagramSocket out = new DatagramSocket();
              out.send(ackPack);
              LogFactory.getLog(getClass())
                  .debug(
                      Thread.currentThread().getName()
                          + " sent ack to "
                          + ackPack.getSocketAddress());
              out.close();
              ackSent.countDown();
              socket.close();
            } catch (Exception e) {
              listening.countDown();
              e.printStackTrace();
            }
          }
        };
    Executor executor = Executors.newFixedThreadPool(2);
    executor.execute(catcher);
    executor.execute(catcher);
    assertTrue(listening.await(10000, TimeUnit.MILLISECONDS));
    MulticastSendingMessageHandler handler =
        new MulticastSendingMessageHandler(
            multicastAddress, testPort, true, true, "localhost", 0, 10000);
    handler.setLocalAddress(this.multicastRule.getNic());
    handler.setMinAcksForSuccess(2);
    handler.afterPropertiesSet();
    handler.start();
    waitAckListening(handler);
    ackPort.set(handler.getAckPort());
    ackListening.countDown();
    handler.handleMessage(MessageBuilder.withPayload(payload).build());
    assertTrue(ackSent.await(10000, TimeUnit.MILLISECONDS));
    handler.stop();
    socket.close();
  }