2012-10-05 13 views
6

Próbuję wysłać UDP z datagramem w języku JAVA, a moja maszyna ma kilka kart sieciowych z różnymi adresami IP.JAVA ustaw/wybierz określoną kartę sieciową z wielu (UDP)

Jak ustawić, której karty sieciowej chcę, aby mój pakiet był wysyłany? (Zakładając, że mam więcej niż jeden na maszynie ??)

EDIT I ​​

nie używam Socket używam DatagramSocket i starał się nie wiążącym tak:

/*binding */ 
     DatagramSocket ds = new DatagramSocket(1111); 
     NetworkInterface nif = NetworkInterface.getByIndex(nicIndex); 
     Enumeration<InetAddress> nifAddresses = nif.getInetAddresses(); 
     ds.bind(new InetSocketAddress(nifAddresses.nextElement(), 0)); 

ale kiedy Robię tak, nie mogę się już połączyć (lub nie mogę pobrać pakietu ...). Problem polega na tym, że mam 2 NIC, ale jedno jest dla sieci wewnętrznej, a drugi jest na Internecie .. muszę wszystkie moje dane serwera iść tylko na wewnętrznym jednego ..

EDIT II

Do wyjaśnienia. Ta aplikacja jest serwerem - a SERWER ma 2 NICS. jedna sieć LAN i jedna sieć WAN.

Alternatywnym sposobem dla mnie byłoby określić trasowanie jakoś - czyli każdy pakiet powiedzieć dokładnie, które używać NIC ..

Jak zrobić taki routing w JAVA ??

Odpowiedz

2

Klasa ma constructor, która przyjmuje argument localAddr. To może dotyczyć Ciebie?

Edytuj: 1) Nie rutuj w Javie, pozostaw to w systemie operacyjnym.

2) Ufam, że odwiedziłeś All About Datagrams?

3) Serwer może wiązać się 0.0.0.0 (czyli każdy IP na komputerze), który jest tym, co się dzieje, jeśli tylko określ port w konstruktorze DatagramSocket lub może wiązać się z określonym interfejsem jeśli zdecydujesz konstruktora DatagramSocket(int port, InetAddress laddr) - to co powinieneś zrobić!

4) Następnie klient wysyła wszystko, co jest potrzebne do wysłania, a serwer może odpowiedzieć, korzystając z gniazda utworzonego w 3) i docelowego pakietu packet.getAddress()/packet.getPort().

Cheers,

+0

Używam klasy DatagramSocket, przeczytaj edytuj I – user1722362

+0

Verdammt - przepraszam za brakujące. Jestem trochę ciekaw, dlaczego chcesz rozwiązać ten problem w kodzie zamiast polegać na routingu IP? Jeśli wyślesz pakiet UDP do danego adresu IP, a ten serwer znajduje się w sieci wewnętrznej, stos IP powinien automatycznie trasować ten pakiet za pośrednictwem odpowiedniego interfejsu NIC. Czy jeszcze brakuje mi czegoś więcej? –

+0

Czy jesteś pewien, że pierwszym elementem w wyliczeniu jest zawsze preferowana karta sieciowa - a jeśli jest to interfejs pętli zwrotnej lub jakiś egzotyczny interfejs tunelu 6to4? –

1

Od Tutorial docs Here, „Aby przesłać dane, system określa, który jest używany interfejs. Jednakże, jeśli masz preferencje czy inaczej trzeba określić, które używać NIC, można wyszukać system dla odpowiednich interfejsów i znajdź adres w interfejsie, którego chcesz użyć. "

Dostęp do NetworkInterFaces można programowo uzyskać, jako,
Wyliczenie en = NetworkInterface.getNetworkInterfaces();

Iterowanie każdego z nich można powiązać z InetAddress i użyć InetAddress do zbudowania gniazda datagramowego.
Jest dobre informacji w tej kwestii - How to enumerate IP addresses of all enabled NIC cards from Java?

nadzieję, że pomoże,

0

Oto głównie kompletny kod użyłem. W moim przypadku znam prefiks adresu IP używany przez moje połączenie. Może zajść potrzeba wyszukania nazwy interfejsu i porównania go z wartością, którą przechowujesz w pliku konfiguracyjnym.

Należy zwrócić uwagę na użycie MulticastSocket zamiast DatagramSocket, aby dostępna była metoda setNetworkInterface w celu powiązania pożądanego interfejsu. Ponieważ MulticastSocket jest klasą potomną DatagramSocket, przełącznik zazwyczaj nie powoduje żadnych problemów.

@Override 
public void connect() throws InterruptedException 
{ 

    NetworkInterface iFace; 

    iFace = findNetworkInterface(); 

    connectControlBoard(iFace); 

    connectUTBoards(iFace); 

}//end of Capulin1::connect 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
// Capulin1:findNetworkInterface 
// 
// Finds the network interface for communication with the remotes. Returns 
// null if no suitable interface found. 
// 
// The first interface which is connected and has an IP address beginning with 
// 169.254.*.* is returned. 
// 
// NOTE: If more than one interface is connected and has a 169.254.*.* 
// IP address, the first one in the list will be returned. Will need to add 
// code to further differentiate the interfaces if such a set up is to be 
// used. Internet connections will typically not have such an IP address, so 
// a second interface connected to the Internet will not cause a problem with 
// the existing code. 
// 
// If a network interface is not specified for the connection, Java will 
// choose the first one it finds. The TCP/IP protocol seems to work even if 
// the wrong interface is chosen. However, the UDP broadcasts for wake up calls 
// will not work unless the socket is bound to the appropriate interface. 
// 
// If multiple interface adapters are present, enabled, and running (such as 
// an Internet connection), it can cause the UDP broadcasts to fail. 
// 

public NetworkInterface findNetworkInterface() 
{ 

    logger.logMessage(""); 

    NetworkInterface iFace = null; 

    try{ 
     logger.logMessage("Full list of Network Interfaces:" + "\n"); 
     for (Enumeration<NetworkInterface> en = 
       NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { 

      NetworkInterface intf = en.nextElement(); 
      logger.logMessage(" " + intf.getName() + " " + 
               intf.getDisplayName() + "\n"); 

      for (Enumeration<InetAddress> enumIpAddr = 
        intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { 

       String ipAddr = enumIpAddr.nextElement().toString(); 

       logger.logMessage("  " + ipAddr + "\n"); 

       if(ipAddr.startsWith("/169.254")){ 
        iFace = intf; 
        logger.logMessage("==>> Binding to this adapter...\n"); 
       } 
      } 
     } 
    } 
    catch (SocketException e) { 
     logger.logMessage(" (error retrieving network interface list)" + "\n"); 
    } 

    return(iFace); 

}//end of Capulin1::findNetworkInterface 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
// Capulin1::connectControlBoards 
// 

public void connectControlBoard(NetworkInterface pNetworkInterface) 
                throws InterruptedException 
{ 

    logger.logMessage("Broadcasting greeting to all Control boards...\n"); 

    MulticastSocket socket; 

    try{ 
     socket = new MulticastSocket(4445); 
     if (pNetworkInterface != null) { 
      try{ 
       socket.setNetworkInterface(pNetworkInterface); 
      }catch (IOException e) {}//let system bind to default interface 
     } 

    } 
    catch (IOException e) { 
     logSevere(e.getMessage() + " - Error: 204"); 
     logger.logMessage("Couldn't create Control broadcast socket.\n"); 
     return; 
    } 

...use the socket here... 
2

Po prostu miałem ten sam problem z tobą. To nie była natychmiastowa, aby rozwiązać ten problem, ale w końcu napisałam trochę kodu, które mogą być przydatne dla Ciebie:

//set Network Interface 
     NetworkInterface nif = NetworkInterface.getByName("tun0"); 
     if(nif==null){ 
      System.err.println("Error getting the Network Interface"); 
      return; 
     } 
     System.out.println("Preparing to using the interface: "+nif.getName()); 
     Enumeration<InetAddress> nifAddresses = nif.getInetAddresses(); 
     InetSocketAddress inetAddr= new InetSocketAddress(nifAddresses.nextElement(),0); 

     //socket.bind(new InetSocketAddress(nifAddresses.nextElement(), 0)); 
     DatagramSocket socket = new DatagramSocket(inetAddr); 
     System.out.println("Interface setted"); 

Kiedyś dużo mocy, aby upewnić się, że kod działa poprawnie i że wyglądają jak to zrobić Nadal nad tym pracuję, ale przypuszczam, że to może wystarczyć dla twojego problemu.

Powiązane problemy