【Android】TCP轮询扫描局域网设备
来源:互联网 发布:linux tar压缩目录 编辑:程序博客网 时间:2024/06/09 06:09
1.前言
最近在做一个局域网通讯的项目,其通讯原理是扫描局域网内存在的设备,扫描完后后发送Socket验证消息到指定设备上,如果获取到返回消息,则表明扫描到目标设备,记录设备信息到设备列表,如果Socket连接超时,则不予记录。
2.TCP轮询扫描
开启扫描时,先获取本机IP地址(如:192.168.1.105),然后使用ping命令轮询本网内可能存在的IP地址(192.168.1.1~192.168.1.255)。如果ping命令返回值正常,记录当前IP地址,当完成轮询任务后,开启设备验证任务,使用Socket发送验证消息到所有扫描成功的IP地址上(使用Socket.connect(SocketAddress remoteAddr, int timeout)来进行连接)用于获取设备信息,如果获取到返回值,则记录设备信息,如果出现连接超时,则不予记录。
3.TCP轮询的优缺点
1 优点
1.低丢包率:能够有效规避通讯丢包情况,避免扫描盲区;
2.扫描全面:在不考虑耗时的情况下,扫描结果还是比较全面的。
2 缺点
1.受网络状态影响:在网络状态不佳的情况下,容易遗漏设备(即双方通讯不通畅导致忽略);
2.耗时过长:如果为轮询设置连接超时(TimeOut)过长的话,会造成整个轮询过程的用时会比较长,不利于快速扫描;
3.负荷较大:如果采用多线程的方式来缩短整体扫描的时间,会增大当前应用负荷。
4.相关代码
package com.zihao.nw.test;import java.net.InetAddress;import java.net.NetworkInterface;import java.net.SocketException;import java.util.ArrayList;import java.util.Enumeration;import java.util.List;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import org.apache.http.conn.util.InetAddressUtils;import android.text.TextUtils;import android.util.Log;/** * @ClassName:ScanDeviceTool * @Description:TODO<局域网扫描设备工具类> * @author:zihao * @date:2015年9月10日 下午3:36:40 * @version:v1.0 */public class ScanDeviceTool { private static final String TAG = ScanDeviceTool.class.getSimpleName(); /** 核心池大小 **/ private static final int CORE_POOL_SIZE = 1; /** 线程池最大线程数 **/ private static final int MAX_IMUM_POOL_SIZE = 255; private String mDevAddress;// 本机IP地址-完整 private String mLocAddress;// 局域网IP地址头,如:192.168.1. private Runtime mRun = Runtime.getRuntime();// 获取当前运行环境,来执行ping,相当于windows的cmd private Process mProcess = null;// 进程 private String mPing = "ping -c 1 -w 3 ";// 其中 -c 1为发送的次数,-w 表示发送后等待响应的时间 private List<String> mIpList = new ArrayList<String>();// ping成功的IP地址 private ThreadPoolExecutor mExecutor;// 线程池对象 /** * TODO<扫描局域网内ip,找到对应服务器> * * @return void */ public void scan() { mDevAddress = getLocAddress();// 获取本机IP地址 mLocAddress = getLocAddrIndex(mDevAddress);// 获取本地ip前缀 Log.d(TAG, "开始扫描设备,本机Ip为:" + mDevAddress); if (TextUtils.isEmpty(mLocAddress)) { Log.e(TAG, "扫描失败,请检查wifi网络"); return; } /** * 1.核心池大小 2.线程池最大线程数 3.表示线程没有任务执行时最多保持多久时间会终止 * 4.参数keepAliveTime的时间单位,有7种取值,当前为毫秒 * 5.一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响 * ,一般来说,这里的阻塞队列有以下几种选择: */ mExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_IMUM_POOL_SIZE, 2000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>( CORE_POOL_SIZE)); // 新建线程池 for (int i = 1; i < 255; i++) {// 创建256个线程分别去ping final int lastAddress = i;// 存放ip最后一位地址 1-255 Runnable run = new Runnable() { @Override public void run() { // TODO Auto-generated method stub String ping = ScanDeviceTool.this.mPing + mLocAddress + lastAddress; String currnetIp = mLocAddress + lastAddress; if (mDevAddress.equals(currnetIp)) // 如果与本机IP地址相同,跳过 return; try { mProcess = mRun.exec(ping); int result = mProcess.waitFor(); Log.d(TAG, "正在扫描的IP地址为:" + currnetIp + "返回值为:" + result); if (result == 0) { Log.d(TAG, "扫描成功,Ip地址为:" + currnetIp); mIpList.add(currnetIp); } else { // 扫描失败 Log.d(TAG, "扫描失败"); } } catch (Exception e) { Log.e(TAG, "扫描异常" + e.toString()); } finally { if (mProcess != null) mProcess.destroy(); } } }; mExecutor.execute(run); } mExecutor.shutdown(); while (true) { try { if (mExecutor.isTerminated()) {// 扫描结束,开始验证 Log.d(TAG, "扫描结束,总共成功扫描到" + mIpList.size() + "个设备."); break; } } catch (Exception e) { // TODO: handle exception } try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * TODO<销毁正在执行的线程池> * * @return void */ public void destory() { if (mExecutor != null) { mExecutor.shutdownNow(); } } /** * TODO<获取本地ip地址> * * @return String */ private String getLocAddress() { String ipaddress = ""; try { Enumeration<NetworkInterface> en = NetworkInterface .getNetworkInterfaces(); // 遍历所用的网络接口 while (en.hasMoreElements()) { NetworkInterface networks = en.nextElement(); // 得到每一个网络接口绑定的所有ip Enumeration<InetAddress> address = networks.getInetAddresses(); // 遍历每一个接口绑定的所有ip while (address.hasMoreElements()) { InetAddress ip = address.nextElement(); if (!ip.isLoopbackAddress() && InetAddressUtils.isIPv4Address(ip .getHostAddress())) { ipaddress = ip.getHostAddress(); } } } } catch (SocketException e) { Log.e("", "获取本地ip地址失败"); e.printStackTrace(); } Log.i(TAG, "本机IP:" + ipaddress); return ipaddress; } /** * TODO<获取本机IP前缀> * * @param devAddress * // 本机IP地址 * @return String */ private String getLocAddrIndex(String devAddress) { if (!devAddress.equals("")) { return devAddress.substring(0, devAddress.lastIndexOf(".") + 1); } return null; }}
1 0
- 【Android】TCP轮询扫描局域网设备
- WIFI管家实现原理:局域网设备扫描
- Android 扫描wifi局域网ip
- Android 扫描wifi局域网ip
- Android BLE设备扫描
- Android网络编程TCP、UDP(三)——UDP实例:搜索局域网所有的设备
- Android网络编程TCP、UDP(三)——UDP实例:搜索局域网所有的设备
- Android网络编程TCP、UDP(三)——UDP实例:搜索局域网所有的设备
- 局域网扫描
- android-扫描周围蓝牙设备
- Android蓝牙扫描设备过程
- 局域网内android设备发现及通讯
- Android端搜索局域网中的设备
- Android获取局域网设备名称方法
- android局域网通信(udp,tcp等)
- Android:手机扫描局域网所有ip,并进行socket通讯
- Android设备二维码扫描竖屏显示
- Android设备获取扫码枪扫描内容
- 手把手教你画一个 逼格满满圆形水波纹loadingview Android
- UITextField输入字符长度判断
- sed命令的使用
- python爬虫爬取糗事百科
- iOS开发UI篇—核心动画(关键帧动画)
- 【Android】TCP轮询扫描局域网设备
- hibernate中lazy的使用
- CSR蓝牙初始化流程
- Linux禁止非WHEEL用户使用SU命令
- django中使用jquery ajax post数据出现403错误的解决办法(两种方法)
- Android 5.0 API新增和改进
- 读《经济解释》卷一,之前
- opengl 分析
- Spring AOP+EHcache配置