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

6

20

Starting from ICS, Wi-Fi Direct is introduced. Normally, we use the WifiP2pManager class 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.

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

Falcon answered 7/4, 2012 at 9:41 Comment(0)
T
19

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.

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

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.

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.

Good luck...

Totter answered 12/4, 2012 at 15:19 Comment(2)
Warning: this code returns the first IP address thats not the loopback, if you are connected to a wifi access point as well as wifi direct, its possible for it to return the address of the access point. From what I have seen the network used by Wifi Direct is the 192.168.49.0 range so you should check if its in that range or better yet compare the owner's host address to ensure they're are on the same network.Kliber
From past forum post, I have found out that it is possible to get client ip by the master(group owner) if i can create a TCP connection. But for UDP connection, how it will be possible to get client ip address? Thank you.Malaco
C
13

The best answer you can get is possibly the one from 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.

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:

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 mPort and receive the connection on the group owner like this:

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 WifiP2pDevice only provides MAC and InetAddress the IP (Does anyone know if there's a way to get the MAC from an InetAddress object?)

Cardwell answered 25/1, 2013 at 16:10 Comment(1)
I had the same problem, searched a lot and ended up doing the same. This seems like the best way which does not rely on some internal system interface and thus doesn't seem prone to breaking in the future!Josephson
P
5

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:

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

I hope it helps you!

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

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;
}
Premeditate answered 3/8, 2012 at 6:28 Comment(5)
this methods is from project from url which you put bellow... I tried use this app.. but, it didn't work... two other crashes was happened.. I can't recommend try to use this method anyone... because he always return null..Beverly
In this I was able to retrieve the values of the connected wifi network only. It is not providing the values of WiFi Direct.Parris
This is code is working great. I am able to retrieve the connected WiFi Direct IP Address.Parris
@ Teja : could you explain further, how you are able to retrieve the connected WiFi Direct IP Address. Because i am only getting IP address of wifi network. not wifi direct.Malaco
this seems really hacky and prone to breakJosephson
A
3

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.

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 :

  • 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)

From that you have all that you need !

If you are the groupOwner => Listen for a connection

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

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 !!!

Amosamount answered 18/10, 2015 at 8:23 Comment(0)
S
2

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.

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();
            }
    }

host is the address of the group owner we get from the connection info.

Skelly answered 14/4, 2014 at 18:11 Comment(1)
Thanks. I am having Host IP, but what I need to place in port number. In App I am using 8000. Can I use it?Parris
T
1

Please use this method to get IP address.

  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; }
         */
    }
Tempered answered 24/4, 2015 at 5:42 Comment(7)
well. since you now know how to find own ip address, then your ip address will be either 192.168.69.1(server) or 192.168.69.*(client). If the device gets server ip, setup server socket in that device and try to connect to that server socket from the device that gets client IP. Now after you establish TCP connection this way, you can transfer whatever information that you need two way. It can be ip address, mac address, files etc. Its all upto you now. Cheers.Tempered
correction: I can get my wifi-direct ip address 192.168.49.1 if i am the group ownwer. but if i am a client i cannot get my own wifi-direct ip address. it is very important to know client ip address so it is possible to send this info to group owner.Malaco
if connection is established, that function will 99% of times retrieve the ip address of any of your wifi direct device.Tempered
i have created connection using, mManager.connect(mChannel, mconfig, new ActionListener() { }. But not connected using socket. Will this code work after after connected by socket?Malaco
I would like to know the location inside the code, where i should call "String getIpAddress()". Thank you for the reply @ Dipendra.Malaco
From past forum post, I have found out that it is possible to get client ip by the master(group owner) if i can create a TCP connection. But for UDP connection, how it will be possible to get client ip address? Thank you.Malaco
What is Globals.thisDeviceAddress? Where is that coming from ?Pinkiepinkish

© 2022 - 2024 — McMap. All rights reserved.