android如何判断两台设备在同一个局域网内
16lz
2021-01-23
android如何判断两台设备在同一个局域网内
目录
- android如何判断两台设备在同一个局域网内
- 第一种方法,比较(ip与netMask)的值
- 第二种方法,根据TTL跳数判定在不在同一个局域网
判断两台设备在不在同一个局域网内有两种方法:
第一种方法是:分别拿到两台设备的ip地址(int类型的ip)和子网掩码(int类型的netMask),然后得到两台设备 ip and netMask 的值,如果相同就是在同一个局域网内,否则就不是。
第二种方法是:通过ping命令,得到TTL跳数,如果TTL跳数不是32,64,128,255之一,代表不是在同一个局域网。
第一种方法,比较(ip与netMask)的值
这种方法主要是根据ip地址(ip)和和子网掩码(netMask)判断的。首先查询ip和netMask,android端代码如下:
var wifiManager = context..getSystemService(Context.WIFI_SERVICE) as WifiManagervar dhcpInfo = wifiManager.getDhcpInfo();var ipAddress = dhcpInfo.ipAddress;//ip地址,int类型的var gateway = dhcpInfo.gateway;//网关地址,int类型的var netmask = dhcpInfo.netmask;//子网掩码,int类型的然后比较两个设备的 ipAddress and netmask 与运算的值是不是相等
需要权限
第二种方法,根据TTL跳数判定在不在同一个局域网
这个方法主要是通过ping命令,来得到TTL跳数,根据TTL跳数来判断。每台设备上TTL都有一个初始值,一般是32,64(常见),128,255(常见)。如果两台设备在同一个局域网,那么TTL就是32、64、128、255这4个数中的一个;
反之如果两台设备不在同一个局域网内,中间有路由器转发,那么
ping命令,相信大家都很熟悉,这里就不多说了。如果不懂的可以百度,网上有很多这方面的资料。直接上代码:
fun isInSameLAN(ipAddress: String): Boolean { var isInSameLAN = false try { val process = Runtime.getRuntime().exec("ping -c 1 -w 1 $ipAddress") var returnMsg = LineNumberReader(InputStreamReader(process.inputStream)).use { var sb = StringBuilder() var readLine: String? while (true) { readLine = it.readLine() ?: break sb.append(readLine) } sb.toString() } val splits = returnMsg.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() for (i in splits.indices) { val split = splits[i] if (split.contains("ttl")) { if (split.contains("32") || split.contains("64") || split.contains("128") || split.contains("255")) { isInSameLAN = true } } } } catch (e: IOException) { e.printStackTrace() } return isInSameLAN }
代买如下:
package jaydenxiao.com.sameintranetimport android.content.Contextimport android.net.wifi.WifiManagerimport java.io.IOExceptionimport java.io.InputStreamReaderimport java.io.LineNumberReaderimport java.util.*object SameLAN { fun getWifiManager(context: Context): WifiManager { return context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager } /** * 获取IP地址。此方法获取的是转换后的ip地址 * @param context * @return 转换后的IP地址: 类似 192.168.1.163 */ fun getIpAddress(context: Context): String { return toIP(getIpAddressInt(context)) } /** * 获取IP地址。此方法获取的是没有转换的int类型的ip地址 * @param context * @return 没有转换的ip地址:类似 -1560172352 */ fun getIpAddressInt(context: Context): Int { val dhcpInfo = getWifiManager(context).dhcpInfo return dhcpInfo.ipAddress } /** * 获取网关。转换后的网关 * @param context * @return 转换后的网关:类似 192.168.1.1 */ fun getGateway(context: Context): String { return toIP(getGatewayInt(context)) } /** * 获取网关。此方法获取的是没有转换的int类型的网关 * @param context * @return 没有转换的网关:类似 16885952 */ fun getGatewayInt(context: Context): Int { val dhcpInfo = getWifiManager(context).dhcpInfo return dhcpInfo.gateway } /** * 获取子网掩码。获取的是转换后的子网掩码 * @param context * @return 换后的子网掩码: 类似 255.255.255.0 */ fun getNetmask(context: Context): String { return toIP(getNetmaskInt(context)) } /** * 获取子网掩码。此方法获取的是没有转换的int类型的子网掩码:16777215 * @param context * @return 没有转换的子网掩码:类似16777215 */ fun getNetmaskInt(context: Context): Int { val dhcpInfo = getWifiManager(context).dhcpInfo return dhcpInfo.netmask } /** * 判断是不是在同一个局域网。 * 原理是分别计算两部手机的 IP地址&子网掩码 的值,如果相等则表示在同一个局域网。 * @param localAddress :本机的IP地址。这个IP地址是String类型的IP地址,详细请看{@link SameLAN#getIpAddress} * @param localMask :本机的子网掩码。这个子网掩码是String类型的子网掩码,详细请看{@link SameLAN#getNetmask} * @param otherAddress :另一部手机的IP地址。这个IP地址是String类型的IP地址,详细请看{@link SameLAN#getIpAddress} * @param otherMask :另一部手机的子网掩码。这个子网掩码是String类型的子网掩码,详细请看{@link SameLAN#getNetmask} * @return :{@code true : 表示在同一个局域网} {@code false : 表示不在同一个局域网} */ fun isInSameLAN(localAddress : String, localMask: String, otherAddress: String, otherMask: String): Boolean { return isInSameLAN(toInt(localAddress),toInt(localMask),toInt(otherAddress),toInt(otherMask)) } /** * 判断是不是在同一个局域网。 * 原理是分别计算两部手机的 IP地址&子网掩码 的值,如果相等则表示在同一个局域网。 * @param localAddress :本机的IP地址。这个IP地址是没有转换后的IP地址,详细请看{@link SameLAN#getIpAddressInt} * @param localMask :本机的子网掩码。这个子网掩码是没有转换后的子网掩码,详细请看{@link SameLAN#getNetmaskInt} * @param otherAddress :另一部手机的IP地址。这个IP地址是没有转换后的IP地址,详细请看{@link SameLAN#getIpAddressInt} * @param otherMask :另一部手机的子网掩码。这个子网掩码是没有转换后的子网掩码,详细请看{@link SameLAN#getNetmaskInt} * @return :{@code true : 表示在同一个局域网} {@code false : 表示不在同一个局域网} */ fun isInSameLAN(localAddress: Int, localMask: Int, otherAddress: Int, otherMask: Int): Boolean { val local = localAddress and localMask val other = otherAddress and otherMask return local == other } /** * 判断是不是在同一个局域网。 * 原理是根据TTL跳数来判断是不是在同一个局域网。他在设备B上有一个初始值,一般是32,64(常见),128,255(常见)。 * 如果AB不能直达,中间有路由器转发,那么每过一个路由,TTL会减一,比如TTL在B的初始值是64,到A是62,说明中间被两个路由转发过。 * 运用这个原理,当A去ping B的时候返回值如果不是32,64,128,255之一,而是略小于其中一个(比如62),那么说明A到B之间有路由器转发,即AB不在同一局域网内。 * @param ipAddress :需要确定是不是在同一个局域网的另一个IP。可以是 "192.168.4.174",也可以是 "www.baidu.com" * @return {@code true : 表示在同一个局域网} {@code false : 表示不在同一个局域网} */ fun isInSameLAN(ipAddress: String): Boolean { var isInSameLAN = false try { val process = Runtime.getRuntime().exec("ping -c 1 -w 1 $ipAddress") var returnMsg = LineNumberReader(InputStreamReader(process.inputStream)).use { var sb = StringBuilder() var readLine: String? while (true) { readLine = it.readLine() ?: break sb.append(readLine) } sb.toString() } val splits = returnMsg.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() for (i in splits.indices) { val split = splits[i] if (split.contains("ttl")) { if (split.contains("32") || split.contains("64") || split.contains("128") || split.contains("255")) { isInSameLAN = true } } } } catch (e: IOException) { e.printStackTrace() } return isInSameLAN } /** * 将int类型的ip地址转换成String类型的 * @param ip * @return */ fun toIP(ip: Int): String { val sb = StringBuffer() sb.append(((ip and 0xff) as Int).toString()) sb.append('.') sb.append(((ip shr 8 and 0xff) as Int).toString()) sb.append('.') sb.append(((ip shr 16 and 0xff) as Int).toString()) sb.append('.') sb.append(((ip shr 24 and 0xff) as Int).toString()) return sb.toString() } /** * 将String类型的IP地址转换成int类型的IP地址 * @param ip * @return */ fun toInt(ip: String): Int { val token = StringTokenizer(ip, ".") var result: Int? = 0 result = Integer.parseInt(token.nextToken()) shl 24 result += Integer.parseInt(token.nextToken()) shl 16 result += Integer.parseInt(token.nextToken()) shl 8 result += Integer.parseInt(token.nextToken()) return result!! }}
全部源码
参考资料
更多相关文章
- android游戏开发实例-可局域网对战的飞行棋(一)
- 基于xml类型的压缩数据流的android获取天气的方法
- 【转】Android -- 探究Android的多分辨率支持以及各种类型图标尺
- Android 仿淘宝2017添加地址
- 《局域网聊天——Android》
- 利用gson处理Java反射TypeToken泛型运行时类型擦除
- Android 保存联系人,包括部门\职位\传真\地址\照片