Android Wi-Fi Direct场景下如何获取每台设备的IP地址?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10053385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:20:08  来源:igfitidea点击:

How to get each device's IP address in Wi-Fi Direct scenario?

androidwifiandroid-wifiwifimanagerwifi-direct

提问by nicefuture

Starting from ICS, Wi-Fi Direct is introduced. Normally, we use the WifiP2pManagerclass to operate on Wi-Fi Direct, but it seems that it can only retrieve the GroupOwner IP address after connected. But, actually, any device all came negotiate to become the GroupOwner. In Upper Application, we need to get the peer's IP address, or each peer's IP address in a group so that we can send/communicate with them.

从ICS开始,引入了Wi-Fi Direct。正常情况下,我们使用WifiP2pManager该类对Wi-Fi Direct进行操作,但似乎只有连接后才能检索GroupOwner IP地址。但是,实际上,任何设备都经过协商成为 GroupOwner。在上层应用中,我们需要获取对等体的IP地址,或组中每个对等体的IP地址,以便我们可以与它们发送/通信。

How to get each IP address in Wi-Fi Direct? Include own IP address and each peer in the group?

如何在 Wi-Fi Direct 中获取每个 IP 地址?包括自己的 IP 地址和组中的每个对等点?

回答by Mano

I encountered the same problem. Since both devices know the group owner's ip, it is already possible to send a message to the group owner. The first message you send can contain the ip address of the other device; from then on, bidirectional communication is possible.

我遇到了同样的问题。由于两个设备都知道群主的ip,所以已经可以向群主发送消息。您发送的第一条消息可以包含其他设备的IP地址;从此,双向通信成为可能。

Here's a possibility for retrieving your ip in java:

这是在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());

Wrap this ip in a Serializable object and send it to the group owner like you would send any other object. Consider this the first step in your wifi-direct protocol... Now, the group owner also has an IP to send answers to.

将此 ip 包装在一个 Serializable 对象中,并将其发送给组所有者,就像发送任何其他对象一样。将此视为您的 wifi-direct 协议中的第一步...现在,组所有者也有一个 IP 可以向其发送答案。

This works for me, although I think it's weird that I had to implement this myself and I could only find the group owner ip easily (info.groupOwnerAddress.getHostAddress(); //with info a WifiP2pInfo instance). Maybe there is a comparable way to retrieve the ip of the other peers, but I couldn't find it. Please contact me if you do.

这对我有用,尽管我认为我必须自己实现它很奇怪,而且我只能轻松找到组所有者 ip (info.groupOwnerAddress.getHostAddress(); //with info a WifiP2pInfo instance)。也许有类似的方法可以检索其他同行的ip,但我找不到。如果你这样做,请与我联系。

Good luck...

祝你好运...

回答by scruffy

The best answer you can get is possibly the one from Mano:

您能得到的最佳答案可能是来自 Mano 的答案:

I encountered the same problem. Since both devices know the group owner's ip, it is already possible to send a message to the group owner. The first message you send can contain the ip address of the other device; from then on, bidirectional communication is possible.

我遇到了同样的问题。由于两个设备都知道群主的ip,所以已经可以向群主发送消息。您发送的第一条消息可以包含其他设备的IP地址;从此,双向通信成为可能。

Here is how I implemented it. When I connect a client to the group owner via WiFi Direct, I get the group owner's ip address, and send a message to the group owner over a socket. Something like:

这是我如何实施它。当我通过 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();

You already know mIP(the group owner's IP address), and only have to decide a mPortand receive the connection on the group owner like this:

您已经知道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());
}

This is the actual code I'm using. I'm going to replace this message with some useful info, like a message object containing the MAC of the sender, which can be used to know about MAC-IP relations, since WifiP2pDeviceonly provides MAC and InetAddressthe IP (Does anyone know if there's a way to get the MAC from an InetAddressobject?)

这是我正在使用的实际代码。我将用一些有用的信息替换此消息,例如包含发件人 MAC 的消息对象,可用于了解 MAC-IP 关系,因为WifiP2pDevice仅提供 MAC 和InetAddressIP(有人知道有没有办法从InetAddress对象获取 MAC ?)

回答by ahmontero

I have done a demo project that is able to get each device ip and send data from one device to another (be the group owner or not). The url is:

我做了一个演示项目,它能够获取每个设备的 ip 并将数据从一个设备发送到另一个设备(无论是否是组所有者)。网址是:

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

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

I hope it helps you!

我希望它能帮助你!

EDIT: Basically looking up the IP address in ARP cache like this:

编辑:基本上像这样在 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;
}

回答by akhil

I've been able to connect and send both ways in a WiFi direct network. All devices know the group owner's IP Address. We get the peer IP from a socket created for communication. Somehow getting the IP from the socket at the server side (at the group owner) did not work for me. So, I send the group owner the IP of the individual device from that device itself. To get the IP simply create a socket and bind it to any local port and get the address from this socket and send it over to the owner. I've used an UDP socket but it works well enough with TCP sockets.

我已经能够在 WiFi 直连网络中以两种方式进行连接和发送。所有设备都知道组所有者的 IP 地址。我们从为通信创建的套接字中获取对等 IP。不知何故,从服务器端(组所有者)的套接字获取 IP 对我不起作用。因此,我从该设备本身向组所有者发送单个设备的 IP。要获取 IP,只需创建一个套接字并将其绑定到任何本地端口,然后从该套接字获取地址并将其发送给所有者。我使用了 UDP 套接字,但它与 TCP 套接字一起工作得很好。

DatagramSocket socket=null;
     try {
        socket=new DatagramSocket();
        socket.connect((new InetSocketAddress(host, port)));
        String address=socket.getLocalAddress().getHostAddress();
        ByteBuffer bb=ByteBuffer.allocate(2+address.length());
        bb.putChar('I');
        bb.put(address.getBytes());
        DatagramPacket pkt=new DatagramPacket(bb.array(),2+address.length());
        socket.send(pkt);
        Log.d(WiFiDirectActivity.TAG,"address"+address+"dest"+host);
        Log.d(WiFiDirectActivity.TAG,"send");
    } catch (SocketException e) {
        Log.e(WiFiDirectActivity.TAG,"error socketException");
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        if (socket != null) {
            if (socket.isConnected()) {
                socket.close();
            }
    }

hostis the address of the group owner we get from the connection info.

host是我们从连接信息中获得的组所有者的地址。

回答by acs-team

I have another approach !

我有另一种方法!

When you create the connection between the 2 (or more) devices, you can't set who is the owner and who is (are) the clients.

当您在 2 个(或更多)设备之间创建连接时,您无法设置谁是所有者以及谁是(是)客户端。

The only information that you have about that is when the BroadCast receiver is connected, you receive an object "WifiP2pInfo". This object contain 2 interesting infos :

您拥有的唯一信息是当广播接收器连接时,您会收到一个对象“WifiP2pInfo”。这个对象包含 2 个有趣的信息:

  • The owner ip address (mWifiP2PInfo.groupOwnerAddress). This string start by "/". Don't forget to remove it ! ;)
  • if you are the owner or not (mWifiP2PInfo.isGroupOwner)
  • 所有者 IP 地址 (mWifiP2PInfo.groupOwnerAddress)。该字符串以“/”开头。不要忘记删除它!;)
  • 如果您是所有者与否 (mWifiP2PInfo.isGroupOwner)

From that you have all that you need !

从那里你有你需要的一切!

If you are the groupOwner => Listen for a connection

如果您是 groupOwner => 监听连接

Else create a connection to the owner with the ip address.

否则,使用 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);
}

Hop it can help you !!!

呵呵 可以帮到你!!!

回答by Dipendra

Please use this method to get IP address.

请使用此方法获取 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; }
         */
    }