2010-01-10 7 views
4

Это на Java, но при необходимости я всегда могу вернуться на C через JNI.Как использовать многоадресную рассылку в многопользовательской системе (Java, Linux)

У меня есть система с двумя сетевыми адаптерами, каждая из которых подключена к отдельной подсети. Я хочу использовать многоадресную рассылку (в частности, SDP) для обнаружения других хостов в обеих сетях.

Одна сеть проста: создайте MulticastSocket на указанном порту, joinGroup его, и я получаю пакеты. Простота.

Две сети: пока что невозможно. Я пробовал:

1) создание двух сокетов, привязанных к одному и тому же порту, и использование setInterface() или setNetworkInterface() для «соединения» с правым интерфейсом. Не повезло, даже после различных перестановок setReuseAddress().

2) создать единый сокет, а затем попытаться присоединиться дважды, с двумя вызовами joinGroup (SocketAddress mcastaddr, NetworkInterface netIf). Второй вызов соединения не выполняется.

Решения за пределами Java были бы замечательными. В частности, если бы я мог настроить многоадресные маршруты, которые бы эффективно «объединили» два интерфейса (я мог бы затем посмотреть на каждый пакет, чтобы определить, какая сеть), что было бы хорошо. Как я уже упоминал ранее, в этой среде можно использовать любое количество нативного кода (Linux, с инфраструктурой java Apache «luni»).

Спасибо!

ответ

0

У меня нет разумной установки, чтобы попробовать это здесь, но получающие широковещательные сообщения, не должны требовать MulticastSocket быть связаны с номером порта от адреса многоадресной рассылки и setNetworkInterface используются для установки интерфейса, используемый для исходящих сообщений.

Что бы я попытался создать два разных MulticastSockets (на любом свободном порту), а затем использовать joinGroup (SocketAddress mcastaddr, NetworkInterface netIf) на каждом из них, используя один и тот же многоадресный адрес, но с различными сетевыми интерфейсами.

+0

Когда вы присоединяетесь к группе многоадресной передачи, вы присоединяетесь к адресу, а не к порту. Пакеты многоадресной передачи будут перенаправлены в вашу сетевую карту на порту, указанном в пакете, отправленном, поэтому, если вы не связывались на том же порту, вы его не получите. Таким образом, вы должны * привязываться к этому порту, чтобы получать многоадресные пакеты. Я пробовал это уже ... – Matthieu

0

Вы рассматривали использование ZeroConf для этого?

Проект jmdns имеет чистую реализацию Java, которая должна работать очень хорошо.

2

Я бы рекомендовал использовать JGroups, который абстрагирует все, что вы пытаетесь сделать, если я правильно понимаю ваши потребности. это элегантный и хорошо продуманный фреймворк для многоадресной (и многоадресной семантики, эмулируемый, когда это необходимо).

+0

спас мой день! после бесполезных попыток с java networking api, эта библиотека, похоже, очень подходит для моих нужд. – b10y

7

Кстати, я недавно работал над аналогичной проблемой.

Вот код Java, который делает то, что вы хотите - он собирает пакеты SDP на нескольких интерфейсах. joinGroup используется для «прикрепления» к указанным интерфейсам.

/** 
* Demonstrate multi-homed multicast listening 
* 
* usage: java Multihome eth0 eth1 lo <etc> 
*/ 

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.SocketException; 
import java.util.Enumeration; 
import java.util.HashSet; 
import java.util.Set; 

public class Multihome { 
    // SDP constants 
    public static final String MULTICAST_ADDRESS = "239.255.255.250"; 
    public static final int MULTICAST_PORT = 1900; 

    // args: each arg is the name of an interface. 
    public void doMain(Set<String> args) 
      throws Exception 
    { 
     InetSocketAddress socketAddress = 
       new InetSocketAddress(MULTICAST_ADDRESS, MULTICAST_PORT); 
     MulticastSocket socket = new MulticastSocket(MULTICAST_PORT); 
     Enumeration<NetworkInterface> ifs = 
       NetworkInterface.getNetworkInterfaces(); 

     while (ifs.hasMoreElements()) { 
      NetworkInterface xface = ifs.nextElement(); 
      Enumeration<InetAddress> addrs = xface.getInetAddresses(); 
      String name = xface.getName(); 

      while (addrs.hasMoreElements()) { 
       InetAddress addr = addrs.nextElement(); 

       System.out.println(name + " ... has addr " + addr); 
      } 

      if (args.contains(name)) { 
       System.out.println("Adding " + name + " to our interface set"); 
       socket.joinGroup(socketAddress, xface); 
      } 
     } 

     byte[] buffer = new byte[1500]; 
     DatagramPacket packet = new DatagramPacket(buffer, buffer.length); 

     while (true) { 
      try { 
       packet.setData(buffer, 0, buffer.length); 
       socket.receive(packet); 
       System.out.println("Received pkt from " + packet.getAddress() + 
            " of length " + packet.getLength()); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 

    public static void main(String[] args) 
      throws Exception 
    { 
     Set<String> argSet = new HashSet<String>(); 
     Multihome multi = new Multihome(); 

     for (String arg : args) { 
      argSet.add(arg); 
     } 

     multi.doMain(argSet); 
    } 
}