Как использовать многоадресную передачу в многодомной системе (Java, Linux) - PullRequest
4 голосов
/ 10 января 2010

Это на Java, но я всегда могу вернуться к C через JNI, если это необходимо.

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

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

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

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

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

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

Спасибо!

Ответы [ 4 ]

7 голосов
/ 05 марта 2010

По совпадению, я недавно работал над похожей проблемой.

Вот некоторый код 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);
    }
}
2 голосов
/ 10 января 2010

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

0 голосов
/ 10 января 2010

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

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

0 голосов
/ 10 января 2010

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

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

...