2012-04-07 13 views
18

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

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

ответ

13

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

Wrap Этот IP в Serializable объект и отправить его владельцу группы, как вы бы отправить любой другой объект. Рассмотрим этот первый шаг в вашем Wi-Fi-прямом протоколе ... Теперь у владельца группы также есть IP-адрес для отправки ответов.

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

Успехов ...

+1

Предупреждение: этот код возвращает первый IP-адрес, который не является loopback, если вы подключены к точке доступа Wi-Fi, а также к Wi-Fi Direct, ее возможно вернуть адрес точки доступа. Из того, что я видел, сеть, используемая Wifi Direct, - 192.168.49.0, поэтому вы должны проверить, находится ли его в этом диапазоне или еще лучше сравнить адрес хоста владельца, чтобы убедиться, что они находятся в одной сети. – triggs

+0

Из предыдущего сообщения в форуме, я выяснил, что можно получить клиентский ip хозяином (владельцем группы), если я могу создать TCP-соединение. Но для UDP-соединения, как можно будет получить клиентский IP-адрес? Спасибо. – user1850484

4

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

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; 
} 
+5

этот метод из проекта с URL-адреса, который вы указали ниже ... Я попытался использовать это приложение .. но это не сработало ... произошли две другие аварии .. Я не могу рекомендовать попробовать использовать этот метод кому-либо ... потому что он всегда возвращает null .. –

+0

В этом я смог получить только значения подключенной сети Wi-Fi. Он не обеспечивает значения WiFi Direct. – Teja

+0

Это код работает отлично. Я могу получить подключенный прямой IP-адрес WiFi. – Teja

9

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

я столкнулся с той же проблемой. Так как оба устройства знают группу владельца , то уже можно отправить сообщение группе . Первое отправленное вами сообщение может содержать 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?)

2

Я смог подключиться и отправить оба способа в прямой сети 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 это адрес владельца группы мы получаем от информации о подключении.

+0

Спасибо. У меня есть Host IP, но то, что мне нужно разместить в номере порта. В приложении я использую 8000. Могу ли я использовать его? – Teja

0

Используйте этот метод, чтобы получить 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

хорошо. поскольку теперь вы знаете, как найти собственный IP-адрес, тогда ваш IP-адрес будет либо 192.168.69.1 (сервер), либо 192.168.69. * (клиент). Если устройство получает IP-адрес сервера, установите его в этом устройстве и попытайтесь подключиться к этому серверному соку с устройства, которое получает IP-адрес клиента. Теперь, после установления TCP-соединения таким образом, вы можете передать любую информацию, которая вам нужна двумя способами. Это может быть адрес ip, адрес mac, файлы и т. Д. Его все до вас сейчас. Приветствия. – Dipendra

+0

коррекция: я могу получить свой ip-адрес wifi-direct 192.168.49.1, если я являюсь владельцем группы. но если я клиент, я не могу получить свой собственный ip-адрес wifi-direct. очень важно знать IP-адрес клиента, чтобы можно было отправить эту информацию владельцу группы. – user1850484

+0

Если соединение установлено, эта функция будет в 99% случаев получать IP-адрес любого из ваших прямых устройств Wi-Fi. – Dipendra

1

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

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

Единственная информация, которая у вас есть об этом, - это когда приемник BroadCast подключен, вы получаете объект «WifiP2pInfo». Этот объект содержит 2 интересные Infos:

  • ВЛАДЕЛЕЦ IP-адрес (mWifiP2PInfo.groupOwnerAddress). Эта строка начинается с "/". Не забудьте удалить его! ;)
  • , если вы являетесь владельцем или нет (mWifiP2PInfo.isGroupOwner)

Из того, что у вас есть все, что вам нужно!

Если вы groupOwner => Listen для подключения

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^