Подтвердить что ты не робот

Как получить IP-адрес каждого устройства в сценарии Wi-Fi Direct?

Начиная с ICS, вводится Wi-Fi Direct. Обычно мы используем класс WifiP2pManager для работы с Wi-Fi Direct, но, похоже, он может получить только IP-адрес GroupOwner после подключения. Но, на самом деле, все устройства все пришли, чтобы стать GroupOwner. В верхнем приложении нам нужно получить IP-адрес однорангового узла или каждый одноранговый IP-адрес в группе, чтобы мы могли отправлять/общаться с ними.

Как получить каждый IP-адрес в Wi-Fi Direct? Включить собственный IP-адрес и каждый одноранговый узел в группе?

4b9b3361

Ответ 1

Я столкнулся с той же проблемой. Поскольку оба устройства знают владельца группы ip, уже можно отправить сообщение владельцу группы. Первое отправленное вами сообщение может содержать IP-адрес другого устройства; с этого момента возможна двунаправленная связь.

Здесь есть возможность получить ваш ip в 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());

Оберните этот ip в объект Serializable и отправьте его владельцу группы, как если бы вы отправили любой другой объект. Считайте это первым шагом в вашем прямом протоколе wifi... Теперь у владельца группы также есть IP-адрес для отправки ответов.

Это работает для меня, хотя мне кажется странным, что я должен был реализовать это самостоятельно, и я мог легко найти владельца группы ip легко (info.groupOwnerAddress.getHostAddress();//с информацией о экземпляре WifiP2pInfo). Возможно, есть сопоставимый способ получить ip других сверстников, но я не смог его найти. Пожалуйста, свяжитесь со мной, если вы это сделаете.

Удачи...

Ответ 2

Лучший ответ, который вы можете получить, возможно, один из Mano:

Я столкнулся с той же проблемой. Поскольку оба устройства знают группу владелец 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());
}

Это фактический код, который я использую. Я собираюсь заменить это сообщение на некоторую полезную информацию, например объект сообщения, содержащий MAC отправителя, который может быть использован для определения отношений MAC-IP, поскольку WifiP2pDevice предоставляет только MAC и InetAddress IP (Кто-нибудь знает, есть ли способ получить MAC из объекта InetAddress?)

Ответ 3

Я сделал демонстрационный проект, способный получить каждое устройство ip и отправлять данные с одного устройства на другое (будь то владелец группы или нет). URL-адрес:

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

Надеюсь, это поможет вам!

EDIT: в основном поиск IP-адреса в кеше ARP следующим образом:

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

Мне удалось подключиться и отправить оба способа в прямой сети 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();
            }
    }

host - это адрес владельца группы, который мы получаем из информации о подключении.

Ответ 5

У меня есть другой подход!

Когда вы создаете соединение между двумя (или более) устройствами, вы не можете установить, кто является владельцем и кто является (являются) клиентами.

Единственная информация, которая у вас есть о том, когда подключен приемник 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);
}

Хоп это может помочь вам!!!

Ответ 6

Пожалуйста, используйте этот метод для получения 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; }
         */
    }

Ответ 7

Еще один способ, еще не упомянутый, использовать WifiP2pGroup. После подключения к одноранговому узлу (или группе) вызовите requestGroupInfo() в диспетчере и дождитесь, пока GroupInfoListener предоставит WiFiP2pGroup. Оттуда вы можете вызвать getClientList() для Коллекции WifiP2pDevice и, следовательно, адреса. Удачного кодирования.