ICSから、Wi-Fi Directが導入されました。通常、WifiP2pManager
クラスを使用してWi-Fi Directを操作しますが、GroupOwner IPアドレスは接続後にしか取得できないようです。しかし、実際には、どのデバイスもすべてGroupOwnerになるために交渉を行いました。上位アプリケーションでは、ピアのIPアドレス、またはグループ内の各ピアのIPアドレスを取得して、それらと送信/通信できるようにする必要があります。
Wi-Fi Directで各IPアドレスを取得する方法は?独自のIPアドレスと各ピアをグループに含めますか?
同じ問題が発生しました。両方のデバイスがグループオーナーのIPを知っているため、メッセージをグループオーナーに送信することはすでに可能です。送信する最初のメッセージには、他のデバイスのIPアドレスを含めることができます。以降、双方向通信が可能になります。
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());
このIPをSerializableオブジェクトでラップし、他のオブジェクトを送信するのと同じようにグループ所有者に送信します。これをwifi直接プロトコルの最初のステップと考えてください...これで、グループの所有者も回答を送信するためのIPを取得しました。
これは私にとってはうまくいきますが、自分で実装する必要があり、グループ所有者のIPを簡単に見つけることができたのは奇妙だと思います(info.groupOwnerAddress.getHostAddress(); //情報を使用してWifiP2pInfoインスタンス)。他のピアのIPを取得するための同等の方法があるかもしれませんが、それを見つけることができませんでした。よろしければご連絡ください。
幸運を...
あなたが得ることができる最良の答えは、おそらく真野からのものです:
同じ問題が発生しました。両方のデバイスがグループオーナーのIPを知っているため、メッセージをグループオーナーに送信することはすでに可能です。送信する最初のメッセージには、他のデバイスのIPアドレスを含めることができます。以降、双方向通信が可能になります。
ここに私がそれを実装した方法があります。 WiFiダイレクト経由でクライアントをグループオーナーに接続すると、グループオーナーの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());
}
これは私が使用している実際のコードです。 WifiP2pDeviceはMACと- InetAddress IP(誰かがInetAddressオブジェクトからMACを取得する方法があるかどうか知っていますか?)
各デバイスのIPを取得し、あるデバイスから別のデバイスにデータを送信できる(グループオーナーであるかどうかにかかわらず)デモプロジェクトを実行しました。 URLは次のとおりです。
https://github.com/ahmontero/wifi-direct-demo
お役に立てば幸いです。
編集:基本的には、次のように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;
}
私は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
は、接続情報から取得するグループオーナーのアドレスです。
別のアプローチがあります!
2つ(またはそれ以上)のデバイス間の接続を作成する場合、誰が所有者で誰がクライアントであるかを設定することはできません。
それに関する唯一の情報は、BroadCastレシーバーが接続されているとき、オブジェクト「WifiP2pInfo」を受け取ります。このオブジェクトには2つの興味深い情報が含まれています。
それからあなたはあなたが必要とするすべてを持っています!
あなたが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);
}
それがあなたを助けることができると思います!!!
このメソッドを使用して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; }
*/
}