package org.kne.cloud.network; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.MulticastSocket; import java.net.NetworkInterface; import java.net.NoRouteToHostException; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.function.Consumer; public class IPMulticastDiscovery extends Thread implements Closeable, AutoCloseable { private MulticastSocket soc; private NetworkInterface ninterface; private volatile boolean closed = false; private InetSocketAddress group; private InetSocketAddress bind; private int type; private List msas; private volatile Consumer con; public NetworkInterface getNinterface() { return ninterface; } public InetSocketAddress getGroup() { return group; } public InetSocketAddress getBind() { return bind; } public Consumer getCon() { return con; } public void setCon(Consumer con) { this.con = con; } public IPMulticastDiscovery(InetSocketAddress bind, InetSocketAddress group, NetworkInterface ninterface, List msas) throws IOException { soc = new MulticastSocket(bind); soc.joinGroup(group, ninterface); this.bind = bind; this.group = group; this.ninterface = ninterface; this.msas = msas; } @Override public void run() { Thread.currentThread().setName("线路发现线程"); ThreadTool.makeVDaemonThreadIfSupport("线路通知线程", () -> { try { while (!closed) { HashSet s = new HashSet(); for (Iterator iterator = msas.iterator(); iterator.hasNext();) { MultipurposeSocketAddress multipurposeSocketAddress = (MultipurposeSocketAddress) iterator .next(); MultipurposeSocketAddress mpsa = new MultipurposeSocketAddress( multipurposeSocketAddress.getType(), "::0", multipurposeSocketAddress.getPort()); try { if (s.add(mpsa)) { boolean bf = true; Enumeration ei = ninterface.getInetAddresses(); while (ei.hasMoreElements()) { InetAddress inetAddress = (InetAddress) ei.nextElement(); if (inetAddress.equals(multipurposeSocketAddress.getInetAddress())) { bf = false; break; } } if (bf) { continue; } ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dops = new DataOutputStream(baos); dops.writeInt(multipurposeSocketAddress.getPort()); dops.writeUTF(multipurposeSocketAddress.getType()); dops.close(); byte[] b = baos.toByteArray(); DatagramPacket dp = new DatagramPacket(b, b.length, group); soc.send(dp); } } catch (NoRouteToHostException|UnknownHostException e) { } } Thread.sleep(10000L); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } finally { try { close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); try { loop:while (!closed) { byte[] b = new byte[65535]; DatagramPacket dp = new DatagramPacket(b, b.length); soc.receive(dp); ByteArrayInputStream bis = new ByteArrayInputStream(b, 0, dp.getLength()); DataInputStream dis = new DataInputStream(bis); int port = dis.readInt(); String type = dis.readUTF(); dis.close(); MultipurposeSocketAddress mpsa = new MultipurposeSocketAddress(type, dp.getAddress().getHostAddress(), port); //System.out.println(mpsa); Enumeration ei = ninterface.getInetAddresses(); while (ei.hasMoreElements()) { InetAddress inetAddress = (InetAddress) ei.nextElement(); if (inetAddress.equals(mpsa.getInetAddress())) { continue loop; } } if (con != null) { con.accept(mpsa); } } } catch (IOException e) { System.out.println(bind + " " + group + " " + ninterface); e.printStackTrace(); } finally { try { close(); } catch (IOException e) { e.printStackTrace(); } } } @Override public void close() throws IOException { soc.close(); closed = true; } public boolean isClosed() { return closed; } }