9

Java でデータグラムを使用して UDP を送信しようとしていますが、マシンには異なる IP を持つ複数の NIC があります。

どの NIC からパケットを送信するかを設定するにはどうすればよいですか?? (マシンに複数あると仮定しますか??)

編集私

私はソケットを使用していません。私は 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 があることですが、1 つは内部ネットワーク用で、もう 1 つはインターネット用です。すべてのサーバー データを内部ネットワークにのみ移動する必要があります。

編集Ⅱ

明確にするために 。このアプリはサーバーであり、サーバーには 2 つの NIC があります。1 つは LAN 用、もう 1 つは WAN 用です。

私にとって別の方法は、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

これは私が使用したほとんど完全なコードです。私の場合、接続で使用される IP アドレスのプレフィックスを知っています。インターフェイスの名前を探して、構成ファイルに保存した値と比較する必要がある場合があります。

DatagramSocket の代わりに MulticastSocket を使用しているため、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 に答える
2

Socketクラスには、引数を取るコンストラクターがあります。localAddrそれはあなたに当てはまるかもしれませんか?

編集: 1)Javaでルーティングを行わず、OSに任せてください。

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 に答える
1

Tutorial docs Hereから、「データを送信するために、システムは使用するインターフェイスを決定します。ただし、好みがある場合、または使用する NIC を指定する必要がある場合は、システムに適切なインターフェイスを照会し、アドレスを見つけることができます。使用したいインターフェース。」


NetworkInterFaces は、 Enumeration en = NetworkInterface.getNetworkInterfaces();のようにプログラムでアクセスできます。

それぞれを繰り返すことで、関連付けられた InetAddress を取得し、InetAddress を使用してデータグラム ソケットを構築できます。
この質問には良い情報があります-Javaから有効なすべてのNICカードのIPアドレスを列挙する方法は?

それが役立つことを願って、

于 2012-10-05T13:28:19.667 に答える