20

ICSから始まり、Wi-Fi Directが導入されました。通常はこのWifiP2pManagerクラスを使って Wi-Fi Direct を操作していますが、接続後に GroupOwner の IP アドレスしか取得できないようです。しかし、実際には、すべてのデバイスが GroupOwner になるようにネゴシエートします。上位アプリケーションでは、ピアの IP アドレス、またはグループ内の各ピアの IP アドレスを取得して、それらと送信/通信できるようにする必要があります。

Wi-Fi Direct で各 IP アドレスを取得するにはどうすればよいですか? 自身の IP アドレスと各ピアをグループに含めますか?

4

6 に答える 6

18

同じ問題が発生しました。両方のデバイスがグループ所有者の IP を知っているため、グループ所有者にメッセージを送信することは既に可能です。送信する最初のメッセージには、他のデバイスの IP アドレスを含めることができます。それ以降は、双方向通信が可能です。

JavaでIPを取得する可能性は次のとおりです。

private byte[] getLocalIPAddress() {
    try { 
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { 
            NetworkInterface intf = en.nextElement(); 
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { 
                InetAddress inetAddress = enumIpAddr.nextElement(); 
                if (!inetAddress.isLoopbackAddress()) { 
                    if (inetAddress instanceof Inet4Address) { // fix for Galaxy Nexus. IPv4 is easy to use :-) 
                        return inetAddress.getAddress(); 
                    } 
                    //return inetAddress.getHostAddress().toString(); // Galaxy Nexus returns IPv6 
                } 
            } 
        } 
    } catch (SocketException ex) { 
        //Log.e("AndroidNetworkAddressFactory", "getLocalIPAddress()", ex); 
    } catch (NullPointerException ex) { 
        //Log.e("AndroidNetworkAddressFactory", "getLocalIPAddress()", ex); 
    } 
    return null; 
}

private String getDottedDecimalIP(byte[] ipAddr) {
    //convert to dotted decimal notation:
    String ipAddrStr = "";
    for (int i=0; i<ipAddr.length; i++) {
        if (i > 0) {
            ipAddrStr += ".";
        }
        ipAddrStr += ipAddr[i]&0xFF;
    }
    return ipAddrStr;
}

ip = getDottedDecimalIP(getLocalIPAddress());

この IP をシリアライズ可能なオブジェクトでラップし、他のオブジェクトを送信する場合と同様にグループ所有者に送信します。これが wifi-direct プロトコルの最初のステップであると考えてください...これで、グループの所有者は回答を送信する IP も持っています。

これは私にとってはうまくいきますが、これを自分で実装する必要があり、グループ所有者の IP を簡単に見つけることしかできなかったのは奇妙だと思います (info.groupOwnerAddress.getHostAddress(); // WifiP2pInfo インスタンスの情報付き)。他のピアの IP を取得する同等の方法があるかもしれませんが、私はそれを見つけることができませんでした。もしよろしければご連絡ください。

幸運を...

于 2012-04-12T15:19:01.963 に答える
13

あなたが得ることができる最良の答えはおそらく真野からのものです:

同じ問題が発生しました。両方のデバイスがグループ所有者のIPを知っているため、グループ所有者にメッセージを送信することはすでに可能です。送信する最初のメッセージには、他のデバイスのIPアドレスを含めることができます。それ以降、双方向通信が可能になります。

これが私がそれをどのように実装したかです。WiFi Directを介してクライアントをグループ所有者に接続すると、グループ所有者のIPアドレスを取得し、ソケットを介してグループ所有者にメッセージを送信します。何かのようなもの:

Socket socket = new Socket();
socket.setReuseAddress(true);
socket.connect((new InetSocketAddress(mIP, mPort)), SOCKET_TIMEOUT);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(new String("BROFIST");
oos.close();
os.close();
socket.close();

あなたはすでにmIP(グループ所有者のIPアドレス)を知っていて、mPortを決定し、次のようにグループ所有者の接続を受信するだけです。

Socket serverSocket = new ServerSocket(mPort);
serverSocket.setReuseAddress(true);
Socket client = serverSocket.accept();
ObjectInputStream objectInputStream = new ObjectInputStream(client.getInputStream());
Object object = objectInputStream.readObject();
if (object.getClass().equals(String.class) && ((String) object).equals("BROFIST")) {
  Log.d(TAG, "Client IP address: "+client.getInetAddress());
}

これは私が使用している実際のコードです。WifiP2pDeviceはMACとIPのInetAddressのみを提供するため、このメッセージを送信者のMACを含むメッセージオブジェクトなどの有用な情報に置き換えます。 InetAddressオブジェクトからMACを取得する方法はありますか?)

于 2013-01-25T16:10:39.493 に答える
5

各デバイスのIPを取得し、あるデバイスから別のデバイスにデータを送信できるデモプロジェクトを実行しました(グループ所有者であるかどうかに関係なく)。URL は次のとおりです。

https://github.com/ahmontero/wifi-direct-demo

お役に立てば幸いです。

編集: 基本的に、次のように ARP キャッシュで IP アドレスを検索します。

public static String getIPFromMac(String MAC) {
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader("/proc/net/arp"));
        String line;
        while ((line = br.readLine()) != null) {

            String[] splitted = line.split(" +");
            if (splitted != null && splitted.length >= 4) {
                // Basic sanity check
                String device = splitted[5];
                if (device.matches(".*p2p-p2p0.*")){
                    String mac = splitted[3];
                    if (mac.matches(MAC)) {
                        return splitted[0];
                    }
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}
于 2012-08-03T06:28:22.610 に答える
2

別のアプローチがあります!

2 つ (またはそれ以上) のデバイス間の接続を作成する場合、所有者とクライアントを設定することはできません。

それについて知っている唯一の情報は、BroadCast 受信機が接続されているときで、オブジェクト「WifiP2pInfo」を受け取ります。このオブジェクトには、2 つの興味深い情報が含まれています。

  • 所有者の IP アドレス (mWifiP2PInfo.groupOwnerAddress)。この文字列は "/" で始まります。それを削除することを忘れないでください! ;)
  • あなたが所有者であるかどうか (mWifiP2PInfo.isGroupOwner)

そこから、必要なものがすべて手に入ります!

あなたが groupOwner の場合 => 接続をリッスンします

それ以外の場合は、IP アドレスを使用して所有者への接続を作成します。

if (mWifiP2PInfo.isGroupOwner) {
    serverSocket = new ServerSocket(port);
    socket = serverSocket.accept();
} else {
    // If the client is not listening when the server create the connection, the connection is not established => Try again
    int retry = 10;

    socket = new Socket();
    socket.bind(null);
    do {
        socket.connect((new InetSocketAddress(mWifiP2PInfo.groupOwnerAddress, port)), 500);
        retry--;
    } while (!socket.isConnected() && retry > 0);
}

それがあなたを助けることができるホップ!!!

于 2015-10-18T08:23:42.773 に答える
1

この方法でIPアドレスを取得してください。

  public static String getIpAddress() {
    try {
        List<NetworkInterface> interfaces = Collections
                .list(NetworkInterface.getNetworkInterfaces());
        /*
         * for (NetworkInterface networkInterface : interfaces) { Log.v(TAG,
         * "interface name " + networkInterface.getName() + "mac = " +
         * getMACAddress(networkInterface.getName())); }
         */

        for (NetworkInterface intf : interfaces) {
            if (!getMACAddress(intf.getName()).equalsIgnoreCase(
                    Globals.thisDeviceAddress)) {
                // Log.v(TAG, "ignore the interface " + intf.getName());
                // continue;
            }
            if (!intf.getName().contains("p2p"))
                continue;

            Log.v(TAG,
                    intf.getName() + "   " + getMACAddress(intf.getName()));

            List<InetAddress> addrs = Collections.list(intf
                    .getInetAddresses());

            for (InetAddress addr : addrs) {
                // Log.v(TAG, "inside");

                if (!addr.isLoopbackAddress()) {
                    // Log.v(TAG, "isnt loopback");
                    String sAddr = addr.getHostAddress().toUpperCase();
                    Log.v(TAG, "ip=" + sAddr);

                    boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);

                    if (isIPv4) {
                        if (sAddr.contains("192.168.49.")) {
                            Log.v(TAG, "ip = " + sAddr);
                            return sAddr;
                        }
                    }

                }

            }
        }

    } catch (Exception ex) {
        Log.v(TAG, "error in parsing");
    } // for now eat exceptions
    Log.v(TAG, "returning empty ip address");
    return "";
}

public static String getMACAddress(String interfaceName) {
        try {
            List<NetworkInterface> interfaces = Collections
                    .list(NetworkInterface.getNetworkInterfaces());

            for (NetworkInterface intf : interfaces) {
                if (interfaceName != null) {
                    if (!intf.getName().equalsIgnoreCase(interfaceName))
                        continue;
                }
                byte[] mac = intf.getHardwareAddress();
                if (mac == null)
                    return "";
                StringBuilder buf = new StringBuilder();
                for (int idx = 0; idx < mac.length; idx++)
                    buf.append(String.format("%02X:", mac[idx]));
                if (buf.length() > 0)
                    buf.deleteCharAt(buf.length() - 1);
                return buf.toString();
            }
        } catch (Exception ex) {
        } // for now eat exceptions
        return "";
        /*
         * try { // this is so Linux hack return
         * loadFileAsString("/sys/class/net/" +interfaceName +
         * "/address").toUpperCase().trim(); } catch (IOException ex) { return
         * null; }
         */
    }
于 2015-04-24T05:42:43.250 に答える