web-dev-qa-db-fra.com

Comment obtenir l'adresse IP de chaque périphérique dans le scénario Wi-Fi Direct?

À partir de ICS, Wi-Fi Direct est introduit. Normalement, nous utilisons la classe WifiP2pManager pour opérer sur Wi-Fi Direct, mais il semble qu’elle ne peut récupérer l’adresse IP de GroupOwner qu’après la connexion. Mais en réalité, tous les appareils sont tous venus négocier pour devenir le GroupOwner. Dans Application supérieure, nous devons obtenir l'adresse IP de l'homologue, ou l'adresse IP de chaque homologue dans un groupe, afin de pouvoir envoyer/communiquer avec eux.

Comment obtenir chaque adresse IP dans Wi-Fi Direct? Inclure sa propre adresse IP et chaque pair du groupe?

18
nicefuture

J'ai rencontré le même problème. Étant donné que les deux appareils connaissent l'adresse IP du propriétaire du groupe, il est déjà possible d'envoyer un message au propriétaire du groupe. Le premier message que vous envoyez peut contenir l'adresse IP de l'autre périphérique. à partir de là, la communication bidirectionnelle est possible. 

Voici une possibilité pour récupérer votre adresse IP en 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());

Enveloppez cette ip dans un objet Serializable et envoyez-la au propriétaire du groupe comme vous enverriez n'importe quel autre objet. Considérez ceci comme la première étape de votre protocole wifi-direct ... Maintenant, le propriétaire du groupe a également une adresse IP à laquelle envoyer des réponses.

Cela fonctionne pour moi, bien que je trouve cela bizarre que je devais l'implémenter moi-même et que je ne puisse que trouver facilement l'ip du propriétaire du groupe (info.groupOwnerAddress.getHostAddress (); // avec info une instance de WifiP2pInfo). Peut-être existe-t-il un moyen comparable de récupérer l'adresse IP des autres pairs, mais je ne pouvais pas le trouver. S'il vous plaît contactez-moi si vous le faites.

Bonne chance...

15
Mano

La meilleure réponse que vous puissiez obtenir est peut-être celle de Mano:

J'ai rencontré le même problème. Puisque les deux appareils connaissent le groupe adresse du propriétaire, il est déjà possible d'envoyer un message au groupe propriétaire. Le premier message que vous envoyez peut contenir l'adresse ip du autre appareil; à partir de là, la communication bidirectionnelle est possible.

Voici comment je l'ai implémenté. Lorsque je connecte un client au propriétaire du groupe via WiFi Direct, je récupère l'adresse IP du propriétaire du groupe et envoie un message au propriétaire du groupe via un socket. Quelque chose comme:

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

Vous connaissez déjà mIP (l'adresse IP du propriétaire du groupe), il vous suffit de choisir un mPort et de recevoir la connexion sur le propriétaire du groupe comme suit:

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

Ceci est le code que j'utilise. Je vais remplacer ce message par des informations utiles, telles qu'un objet de message contenant le MAC de l'expéditeur, qui peuvent être utilisées pour connaître les relations MAC-IP, car WifiP2pDevice fournit uniquement le MAC et InetAddress l'adresse IP (Quelqu'un sait-il s'il existe un moyen d'obtenir le MAC à partir d'un InetAddress object?)

10
scruffy

J'ai réalisé un projet de démonstration capable de récupérer chaque adresse IP de périphérique et d'envoyer des données d'un périphérique à un autre (propriétaire ou non du groupe). L'URL est:

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

J'espère que ça t'aide!

EDIT: Rechercher l’adresse IP dans le cache ARP comme ceci:

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;
}
4
ahmontero

J'ai été en mesure de me connecter et d'envoyer les deux dans un réseau direct WiFi . Tous les périphériques connaissent l'adresse IP du propriétaire du groupe. Nous obtenons l'adresse IP du pair à partir d'un socket créé pour la communication. D'une manière ou d'une autre, obtenir l'adresse IP du socket côté serveur (du propriétaire du groupe) ne fonctionnait pas pour moi. J'envoie donc au propriétaire du groupe l'adresse IP du périphérique individuel à partir de ce périphérique lui-même. Pour obtenir l’IP, il suffit de créer un socket et de le lier à n’importe quel port local, d’obtenir l’adresse de ce socket et de l’envoyer au propriétaire .J'ai utilisé un socket UDP mais cela fonctionne assez bien avec TCP prises de courant.

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 est l'adresse du propriétaire du groupe que nous recevons à partir des informations de connexion.

2
akhil

J'ai une autre approche!

Lorsque vous créez la connexion entre les 2 (ou plus) périphériques, vous ne pouvez pas définir qui est le propriétaire et qui est (sont) les clients.

La seule information que vous avez à ce sujet est que lorsque le récepteur BroadCast est connecté, vous recevez un objet "WifiP2pInfo". Cet objet contient 2 infos intéressantes: 

  • L'adresse IP du propriétaire (mWifiP2PInfo.groupOwnerAddress). Cette chaîne commence par "/". N'oubliez pas de l'enlever! ;)
  • si vous êtes propriétaire ou non (mWifiP2PInfo.isGroupOwner)

De cela, vous avez tout ce dont vous avez besoin!

Si vous êtes le propriétaire de groupe => Écouter une connexion

Sinon, créez une connexion avec le propriétaire avec l'adresse 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 ça peut t'aider !!!

1
acs-team

Veuillez utiliser cette méthode pour obtenir une adresse 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; }
         */
    }
0
Dipendra