9

我正在尝试在 JAVA 中发送带有数据报的 UDP,并且我的机器有几个具有不同 IP 的 NIC。

如何设置我希望从哪个 NIC 发送数据包?(假设我的机器上有不止一个??)

编辑我

我没有使用 Socket,我使用的是 DatagramSocket 并尝试像这样进行绑定:

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

但是当我这样做时,我无法再连接(或无法获取数据包..)。问题是我有 2 个 NIC,但一个用于内部网络,另一个用于 Internet .. 我需要我的所有服务器数据只在内部一个..

编辑二

为了澄清 。这个应用程序是一个服务器 - 并且 SERVER 有 2 个 NICS。一个局域网,一个用于广域网。

对我来说,另一种方法是以某种方式指定 ROUTING - 意思是告诉每个数据包确切地使用哪个 NIC ..

如何在 JAVA 中做这样的路由?

4

4 回答 4

4

我刚遇到你同样的问题。解决问题并没有立即解决,但最后我写了一些对您有用的代码:

//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");

我使用了很多输出来确保代码正常工作并且看起来像这样做,我仍在努力,但我想这足以解决你的问题

于 2015-01-30T08:52:36.380 回答
2

该类Socket有一个带参数的构造localAddr函数。这可能适用于你?

编辑: 1)不要在Java中进行路由,将其留给操作系统。

2) 我相信您访问过All About Datagrams吗?

3)服务器可以绑定到0.0.0.0(即机器上的任何IP),如果你只在DatagramSocket构造函数中指定一个端口,或者如果你选择构造函数它可以绑定到一个特定的接口,就会发生DatagramSocket(int port, InetAddress laddr)这种情况——这就是你应该做的!

4) 客户端然后发送它需要发送的任何内容,服务器可以使用在 3) 中创建的套接字和 packet.getAddress()/packet.getPort() 目标进行响应。

干杯,

于 2012-10-05T09:04:11.813 回答
2

这是我使用的大部分完整代码。就我而言,我知道我的连接使用的 IP 地址前缀。您可能需要查找接口的名称并将其与存储在配置文件中的值进行比较。

请注意使用 MulticastSocket 而不是 DatagramSocket,因此 setNetworkInterface 方法可用于绑定所需的接口。由于 MulticastSocket 是 DatagramSocket 的子类,因此切换通常不会引起任何问题。

@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...
于 2013-11-07T00:57:51.697 回答
1

来自 Tutorial docs Here,“要发送数据,系统会确定使用哪个接口。但是,如果您有偏好或需要指定要使用的 NIC,您可以向系统查询适当的接口并在您要使用的界面。”

NetworkInterFaces 可以通过编程方式访问,
Enumeration en = NetworkInterface.getNetworkInterfaces();

迭代每个你可以获得与之关联的 InetAddress 并使用 InetAddress 来构造你的数据报套接字。
这个问题有很好的信息 -如何从 Java 枚举所有启用的 NIC 卡的 IP 地址?

希望有帮助,

于 2012-10-05T13:28:19.667 回答