我希望能够在我的网络上发现Android设备,并可能检索一些关于它们的设备信息。这对于苹果设备来说非常容易,因为它们运行Bonjour服务。然而,我似乎找不到任何类似的服务运行在Android上。
这必须在不修改Android设备,安装某些服务或打开某些端口的情况下工作。它旨在与vanilla Android设备配合使用,就像Bonjour帮助您找到vanilla Apple设备一样。即使能够验证设备是否运行Android也足够了。
选择的答案:虽然它不是最高评级的答案(还没有),请看看路易斯的回应。正如他提到的,你可以使用DNS查询(使用你的本地DNS服务器)来发现Android设备。我发现这有100%的成功率,因为Android强制设备使用android-____的主机名。这显然很难在手机上改变,即使是根深蒂固的。所以我认为这是一个非常准确的方法。谢谢,路易斯!
Example:
$ nslookup 192.168.1.104 192.168.1.1
Server: 192.168.1.1
Address: 192.168.1.1#53
104.1.168.192.in-addr.arpa name = android-711c129e251f14cf.\001.
示例代码:如果您想在Java中实现它(例如,在Android上运行),您不能轻松使用getHostName(),因为它使用外部DNS服务器。例如,您想在路由器上使用本地DNS服务器。Luis在下面提到,您可以修改Wifi连接的DNS服务器,但这可能会破坏其他东西。相反,我发现dnsjava
库对发送目标DNS请求非常有用。以下是一些使用该库的示例代码:
String ipAddress = "104.1.168.192";
String dnsblDomain = "in-addr.arpa";
Record[] records;
Lookup lookup = new Lookup(ipAddress + "." + dnsblDomain, Type.PTR);
SimpleResolver resolver = new SimpleResolver();
resolver.setAddress(InetAddress.getByName("192.168.1.1"));
lookup.setResolver(resolver);
records = lookup.run();
if(lookup.getResult() == Lookup.SUCCESSFUL) {
for (int i = 0; i < records.length; i++) {
if(records[i] instanceof PTRRecord) {
PTRRecord ptr = (PTRRecord) records[i];
System.out.println("DNS Record: " + records[0].rdataToString());
}
}
} else {
System.out.println("Failed lookup");
}
} catch(Exception e) {
System.out.println("Exception: " + e);
}
这给了我输出:
DNS Record: android-711c129e251f14cf.\001.
答对 了
AFAIK,Android系统在其内置的系统应用程序/服务堆栈上不提供任何zeroconf应用程序/服务器。要在连接到本地网络的实际设备上启用自动发现,您需要安装一些第三方zeroconf应用程序,或者开发自己的应用程序/服务并将其安装在实际设备上,一些API选项包括:
我不太清楚您的要求,如果您想要在普通Android设备上实现类似的功能(即自动发现和连接),您可能可以使用Wi-Fi direct,该功能现在在运行Android 4.0的一些更高版本的设备上可用,但是,它要求两个设备都支持Wi-Fi Direct,并且只能在Wi-Fi关闭的情况下创建点对点P2P连接,很像范围更长的蓝牙连接:
有关Wi-Fi Direct API支持,请查看官方指南-无线连接设备。
Android不会像iOS那么简单。没有与之相当的“你好”。
Android 4.0,Ice Cream Sandwich,引入了Wi-Fi Direct Peer to Peer Networking。起初,我希望它能够以您的想法进行扫描,但它可以帮助Android设备在没有接入点的情况下进行通信,因此它们实际上并不“在您的网络上”。此外,ICS只能在一小部分Android设备上运行。
与主动的netscan方法不同,您只能使用被动的监视方法。如果您的网络是安全的,嗅探加密数据包是可能的,但不方便。你必须
如果你想看到它的实际效果,Wireshark支持WPA解密。
一旦您能够查看Wi-Fi流量,您会注意到Android设备倾向于与某些Google服务器进行通信,并且它们的HTTP连接具有可以识别的用户代理字符串。这是可行的被动解决方案的基础。
Table Network Security提供的产品似乎采用了这种类型的方法。
@Michelle Cannon提到了Libelium的Meshlium Xtreme,它的方法不会让你一路到达目的地(除非有最新的MAC地址范围表)。但这可能是达成一个较小目标的一部分。您可以:
如果您愿意检测可能是Android的设备,这可能是可行的。
@Michelle Cannon建议使用DHCP指纹识别。起初我不确定,但我必须感谢他提出了简单被动扫描的最佳选择。作为一个警告,我想解释一下为什么我迟到了。
在很多方面,Android使用Linux内核是好的。但是如果你想在网络上发现Android设备,那就不好了。Android的TCP/IP堆栈是Linux的,因此Android设备看起来像Linux设备,我一开始是这么想的。但是后来我意识到Linux有很多构建配置参数,所以在网络上看到Android可能会有一些与众不同的地方,但是什么呢?
DHCP指纹识别使用设备请求的确切DHCP选项加上时间。要做到这一点,您通常需要一个最新的指纹数据库来匹配。起初看起来指纹银行被大量采购这些数据,但后来我注意到他们的文件已经快一年没有更新了。对于所有不同的Android设备类型,我认为为一个项目保留更新的指纹是不实际的。
但后来我查看了Android的实际DHCP签名,我注意到了这一点:
Android 1.0: dhcpvendorcode=dhcpcd 4.0.0-beta9
Android 1.5-2.1: dhcpvendorcode=dhcpcd 4.0.1
Android 2.2: dhcpvendorcode=dhcpcd 4.0.15
Android 3.0: dhcpvendorcode=dhcpcd-5.2.10
Linux通常使用dhclient作为其DHCP客户端,但Android使用dhcpcd。Android强烈倾向于尽可能使用BSD风格许可的软件,dhcpcd使用BSD许可。dhcpvendorcode似乎可以作为移动设备运行Android的有力指标。
客户端在加入网络时使用DHCP获取IP地址,因此它开始时没有IP地址。它通过在初始交换中使用UDP广播来解决这个问题。在Wi-Fi上,即使使用WPA,广播流量也不会加密。因此,您只需在UDP端口67上侦听客户端到服务器的流量,而在端口68上侦听相反的流量。您甚至不需要将网络接口设置为混杂模式。您可以使用Wireshark之类的协议分析器轻松监控此流量。
我更喜欢编写代码来监控流量,并决定使用Python。我选择pydhcplib来处理DHCP的细节。我在这个图书馆的经历并不顺利。我需要手动下载并放置IN.py和TYPES.py支持文件。他们的数据包到字符串的转换将dhcpvendorcode留空。它确实正确地解析了DHCP数据包,所以我只编写了自己的打印代码。
下面是监控从客户端到服务器的DHCP流量的代码:
#!/usr/bin/python
from pydhcplib.dhcp_packet import *
from pydhcplib.dhcp_network import *
from pydhcplib.dhcp_constants import *
netopt = {
'client_listen_port':"68",
'server_listen_port':"67",
'listen_address':"0.0.0.0"
}
class Server(DhcpServer):
def __init__(self, options):
DhcpServer.__init__(
self,options["listen_address"],
options["client_listen_port"],
options["server_listen_port"])
def PrintOptions(self, packet, options=['vendor_class', 'host_name', 'chaddr']):
# uncomment next line to print full details
# print packet.str()
for option in options:
# chaddr is not really and option, it's in the fixed header
if option == 'chaddr':
begin = DhcpFields[option][0]
end = begin+6
opdata = packet.packet_data[begin:end]
hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
print option+':', ':'.join([(hex[i/16]+hex[i%16]) for i in opdata])
else:
opdata = packet.options_data.get(option)
if opdata:
print option+':', ''.join([chr(i) for i in opdata if i != 0])
print
def HandleDhcpDiscover(self, packet):
print "DHCP DISCOVER"
self.PrintOptions(packet)
def HandleDhcpRequest(self, packet):
print "DHCP REQUEST"
self.PrintOptions(packet)
## def HandleDhcpDecline(self, packet):
## self.PrintOptions(packet)
## def HandleDhcpRelease(self, packet):
## self.PrintOptions(packet)
## def HandleDhcpInform(self, packet):
## self.PrintOptions(packet)
server = Server(netopt)
while True :
server.GetNextDhcpPacket()
这段代码基于pydhcplib的服务器示例,因为它像服务器一样监听客户端请求。
当我的Nexus 7 Android 4.2平板电脑连接时,会捕获(编辑)此有趣的信息:
DHCP REQUEST
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff
DHCP DISCOVER
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff
主机名似乎有固定的格式,很容易解析。如果您需要IP地址,您可以监控服务器到客户端的流量。注意:当一个没有IP地址的新客户机第一次出现时,只有初始交换会被广播。未来租赁延期等。,都没有播出。
@Luis发布了一个很棒的解决方案,展示了简单越好。即使看到Android的DHCP客户端将host_name设置为android-5c1b97cdffffff,我也没有想到使用反向DNS查找向路由器询问其名称列表。路由器将host_name添加到其DNS服务器,因此如果其IP地址发生变化,您仍然可以访问设备。
在DHCP租约期间,host_name预计将保留在DNS中。您可以通过ping来检查设备是否仍然存在。
依赖于host_name的一个缺点是,有多种方法可以改变这一点。设备制造商或运营商很容易更改host_name(尽管在搜索之后,我无法找到他们曾经拥有的任何证据)。有一些应用程序可以更改主机名,但它们需要root,所以这最多是一种边缘情况。
最后,还有一个开放的 Android 问题 6111:允许指定当前具有 629 颗星的主机名。在未来的某个时候,也许很快就会在Android设置中看到可配置的host_name,这并不奇怪。因此,如果您开始依靠host_name来识别Android设备,请意识到它可以从您身下被拉出。
如果您正在进行实时跟踪,反向DNS查找的另一个潜在问题是您必须决定扫描的频率。(当然,如果您只是拍摄一次性快照,这不是一个问题。)频繁扫描会消耗网络资源,而不频繁扫描会导致数据过时。以下是添加DHCP监控的帮助方式:
虽然这并不容易(也不是100%准确),但有几种技术可以在您的网络上发现Android设备。
有一种非常简单的方法,在一些不同的设备上给我带来了积极的结果。
当设备连接到您的路由器时,它接收IP(即DHCP)并在DNS中注册名称。注册的名称似乎总是采用<code>android_ nnnnnnnn</code>的形式。
当然,你可以用同样的方法命名任何一台计算机,欺骗检查,导致误报...
此外,我无法确保所有设备供应商都遵循相同的方法,但我发现它在我测试过的不同品牌(包括不同SDK级别)的一些设备中都能正常工作。
--编辑--
怎么做
这取决于您将在哪里运行代码来发现Android设备。假设您将在Android设备上运行代码:
>
首先发现您网络中响应ping
的设备。您可以使用我对这篇文章的回答中的代码:execComd()来运行ping命令。
使用以下html" target="_blank">代码获取响应设备的名称:
InetAddress:inetAddresse=inetAddresss.getByName(string_with_ip_addr);
字符串名称=inetAddress.getCanonicalHostName();
--编辑 2--
概念证明
下面的方法只是我上面写的概念的证明。
我正在使用isReachable()
方法来生成ICMP请求,据说在许多帖子中,它仅适用于root设备,用于测试它的设备就是这种情况。但是,我没有为运行此代码的应用程序授予root权限,因此我认为它无法设置SIUD位,这就是某些人声称此方法失败的原因。我想从在无根设备上测试它的人的角度来做。
要呼叫使用:
ArrayList<String> hosts = scanSubNet("192.168.1.");
它在<code>主机
private ArrayList<String> scanSubNet(String subnet){
ArrayList<String> hosts = new ArrayList<String>();
InetAddress inetAddress = null;
for(int i=1; i<10; i++){
Log.d(TAG, "Trying: " + subnet + String.valueOf(i));
try {
inetAddress = InetAddress.getByName(subnet + String.valueOf(i));
if(inetAddress.isReachable(1000)){
hosts.add(inetAddress.getHostName());
Log.d(TAG, inetAddress.getHostName());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return hosts;
}
当做
最近,我们在Android应用程序中增加了对Chromecast的支持,但在对各种移动设备(手机和平板电脑)的扩展测试中,发现在许多移动设备上,Flipps应用程序都没有发现Chromecast。在相同的设备上,我们使用了最新版本的官方Chromecast SDK演示应用程序进行测试,该应用程序从https://github.com/googlecast/castvideo-Android下载(主
所以我在玩Expo+React Native+yoga graphql server+Apollo Client,通过查询获取数据在浏览器中工作,当我从Expo点击“在浏览器中运行”时,但如果我试图在android模拟器/QR code上从真实的手机上运行该应用程序,它会引发网络错误。附言。我在github上阅读了类似的帖子和问题,所以我设法使graphqlendpoint可以通过nat和No-I
尝试使用pybonjour,但不确定它是否是我需要的。https://code.google.com/p/pybonjour/ 我希望能够自动发现出现在我的网络上的iOS设备,稍后将基于此运行一个脚本,但首先我想在它出现/消失在我的wifi网络上时立即发现iOS设备。 所以问题是,我该怎么做?在安装了python27和pybonjour包的windows机器上运行,这两个示例在pybonjour页
我希望能够发现附近的任何类型的设备(10 m),并可能检索到除了MAC地址之外的一些设备信息。这应该通过WIFI发现。 这些设备不需要在同一个网络中(因为大多数问题要求类似的行为),它们可以只是在这个“antena”旁边通过。 设备不断与附近的接入点通信,因此我认为应用程序也能够捕捉这些广播。 我试图使用Android Nsd(网络服务发现),直到我发现这仅适用于同一网络中的设备。我刚刚开始研究
那么有没有办法将flutter应用从windows机器运行到真正的ios设备呢? 我找了找,但找不到答案。我唯一发现的东西是2019年的,我认为这是一个很长的时间,也许开发了一个工具。
我试图发现我的设备连接到的WiFi网络上的所有设备。这是普通的Java,不是Android。我需要搜索每个设备,看看它是否有一个特定的端口打开。我将通过连接到我发现的第一个符合此条件的设备,所以我需要它的IP地址。我基本上是在尝试编写以下代码: