我有两部 Android KitKat 手机,两者都作为组所有者运行 WiFi-Direct 组,我们称它们为 GO1 和 GO2
我设法将 GO1 作为旧客户端连接到 GO2,而没有破坏任何(之前设置的)wifi-direct 组。
问题在于,正如您可能知道的那样,GO IP 地址在 Android 源代码中被硬编码,并设置为 192.168.49.1
因此,我的两个设备 GO1 和 GO2 具有相同的 IP 地址 (**)...每个设备都在其本地网络上。
我的应用程序同时是客户端和服务器。但两个网络都使用相同的 IP 范围 (192.168.49.XXX),显然我无法更改。
因此,如果它们都托管 WiFi-Direct 组,我无法在它们之间创建 TCP 连接,因为任何设备在尝试连接到 192.168.49.1 时都会连接到自身
所以问题是:
** :实际上,由于 GO1 作为旧客户端连接到 GO2,因此 GO1 对于 GO2 来说称为 192.168.49.227(例如),而 GO2 对于 GO1 来说称为 192.168.49.1。但由于 GO1 也是 GO,因此他的客户(及其本身)也将其称为 192.168.49.1。
无需 root 手机即可解决此问题的一种方法是通过多播 UDP* 发送数据包。这些数据包将从 GO1 发送到 GO2。
这样做有一些副作用:
要将其用于网络,您必须在 OSI 应用程序级别执行封装和路由(效率不高)。
您还需要根据 MAC 地址进行路由,因为每个设备都有相同的 192.168.49.1 地址。
“需要注意的是,多播套接字封装了一对多单播通信,因此无法充分利用可用的 WiFi 和 WiFi Direct 总带宽”*
还有一点值得注意:
*此方法在 Colin Funai、Cristiano Tapparello 和 Wendi Heinzelman 题为“通过 WiFi Direct 多组网络支持多跳设备到设备网络”的论文中提到:https://arxiv.org/pdf /1601.00028.pdf
无法更改 IP 范围,因为正如您所正确指出的那样,它是硬编码在 Android Wi-Fi Direct 系统服务中的。就我个人而言,我不知道 Wi-Fi P2P 接口上启用了 IPv6,即使启用了,它也可能是硬编码的 IPv6 地址。
如果 GO1 和 GO2 必须在都处于 GO 模式时相互连接,那么也许可以考虑使用蓝牙或其他传输方式来允许它们进行通信。如果 GO1 和 GO2 之间的通信可以延迟,则缓存要交换的任何信息,并在一个设备可以成为另一个设备的客户端时在这两个设备之间发送该信息,例如当 GO1 可以不再是 GO 并可以成为 GO2 的客户端时。
实际上可以使用 IPv6 链接本地地址来解决这个问题(其中 group 是从广播或请求接收到的 WifiP2pGroup):
val interfaceName = group?.`interface`
val linkInterface = NetworkInterface.getNetworkInterfaces().toList()
.firstOrNull {
it.name == interfaceName
}
val linkLocalAddr = linkInterface?.inetAddresses?.toList()
?.firstOrNull { it.isLinkLocalAddress && it is Inet6Address } as? Inet6Address
IPv6 地址的“范围”是特定的网络接口。使用 IPv6 链路本地地址,您可以向/从 GO1 和 GO2 发送流量。连接设备在自动连接后将无法找到链接本地地址,因此您需要以其他方式广播它(例如使用本地服务发现txt记录