首页 > 代码库 > 在局域网中通过端口号扫描服务器IP
在局域网中通过端口号扫描服务器IP
简要说明
本人才接触Android不就,这个月有个任务是这样的。客户端要和服务器进行Socket通信,由于服务器不固定也就导致了服务器IP不固定,就不能实现于多个服务器通信,于是有了这样一个需求。客户端根据服务器提供的端口号来扫描服务器IP,从而满足这个需求。拿到需求一看,果断不会,于是就百度去了。搜索解雇倒是不少,可是打开一看全是重复的代码,复制——粘贴。仔细一看,就连我这个新手也看出来了很多问题,果断拿来大大修改了一番,废话不多少直接看代码吧:
实现代码:
1 //本地IP 2 private String locAddress; 3 //核心线程数 4 private int corePoolSize = 2; 5 //最大线程数 6 private int maximumPoolSize = 5; 7 //线程池维护线程所允许的空闲时间 8 private long keepAliveTime = 30; 9 //线程池维护线程所允许的空闲时间的单位10 private TimeUnit unit = TimeUnit.SECONDS;1112 //线程池所使用的缓冲队列13 private BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();14 @SuppressWarnings("unused")15 private ThreadPoolExecutor threadPoolExecutor 16 = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
从这段代码可以看出,我主要是定义了一个线程池,之后要开启线程来扫描局域网IP的,百度的方法是直接开启255个线程,我对这种做法真不知道说什么了~~~不多说,直接看方法代码:
1 2 public void scan(final int SERVERPORT){ 3 locAddress = getLocAddrIndex();//获取本地ip前缀 4 5 //开启线程 6 threadPoolExecutor.execute( new connectionServer(SERVERPORT, locAddress,0,100)); 7 threadPoolExecutor.execute( new connectionServer(SERVERPORT, locAddress,101,200)); 8 threadPoolExecutor.execute( new connectionServer(SERVERPORT, locAddress,201,256)); 9 threadPoolExecutor.shutdownNow();10 11 }12
从这个方法是用于外部调用的scan方法,传递端口号,然后开启线程进行扫描,大家都知道,如果在一个局域网的话设备的网段是一样的,比如说:一台电脑和手机都连接了同一个wifi。那么电脑的IP就可能是192.168.8.X,手机IP就是192.168.8.Y。就是说前三个字段是一致的,那我们只要去适配最后一位,那手机就一定有几率来匹配到电脑。这样一来就简单了,最后一位无非就是1~255所以我把这个字段分开来,开启三个线程分别扫描。扫描方法之后会列出来,我们先看看怎么得到局域网前三个字段,也就是举例中的192.168.8
getLocAddrIndex()
方法是获得IP前缀的
1 /** 2 * @return 3 * 获取IP前缀 4 */ 5 6 private String getLocAddrIndex() { 7 String str = getLocAddress(); 8 9 if(!str.equals("")){10 return str.substring(0,str.lastIndexOf(".")+1);11 }12 return null;13 }
可以看到,这个方法只是将getLocAddress()方法获得的本地IP进行了截取,也就是截取出网段。下来放出如何获取本地IP:
1 public static String getLocAddress() { 2 String ipaddress = ""; 3 try { 4 Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); 5 // 遍历所用的网络接口 6 while (en.hasMoreElements()) { 7 NetworkInterface networks = en.nextElement(); 8 // 得到每一个网络接口绑定的所有ip 9 Enumeration<InetAddress> address = networks.getInetAddresses();10 // 遍历每一个接口绑定的所有ip11 while (address.hasMoreElements()) {12 InetAddress ip = address.nextElement();13 if (!ip.isLoopbackAddress()14 && InetAddressUtils.isIPv4Address(ip.getHostAddress())) {15 ipaddress = ip.getHostAddress();16 17 }18 }19 }20 } catch (SocketException e) {21 22 e.printStackTrace();23 }24 25 26 return ipaddress;27 }
这个方法是百度找的,可以获取到设备的IP但是别忘记权限哦。到这里我们也就获取到了网段地址也就是我们所说的192.168.8
接下来放出线程扫描端口的方法:
1 public class connectionServer extends Thread{ 2 private int sERVERPORT;//端口号 3 private String slocAddress;//网段 4 private int sNum;//开始扫描点 5 private int eNum;//结束扫描点 6 public connectionServer(int SERVERPORT, String locAddress,int startNum,int endNum) { 7 sERVERPORT = SERVERPORT; 8 slocAddress = locAddress; 9 sNum = startNum;10 eNum = endNum;11 12 }13 14 @Override15 public void run() {16 for(int i = sNum;i < eNum; i ++){17 18 String current_ip = slocAddress+i;19 if(Call(current_ip, sERVERPORT)){20 onSeekIp(current_ip);21 22 }23 24 } 25 26 }27 }
可以看出来是用了一个构造将需要的参数传递进来。然后在run()方法里用for循环进来匹配 ,关于匹配的方法我要说几句,第一次我用的是命令行匹配的方法也就是- p - l 也就是先用了下Window DOS下的ping命令能平通的再尝试和服务器连接。可是后来发现有好多设备无法执行这个命令,比如 鄙人用的小米手机可以,同事的魅族就无法执行了,找来找去发现socket就有一个判断端口是否打开的方法,正式踏破铁屑无觅处,得来全不费工夫啊,各位看官,请看代码:
1 //判断端口是否打开 2 public boolean Call(String ip, int port) { 3 4 try { 5 Socket socket = new Socket(); 6 socket.connect(new InetSocketAddress(ip, port), 15); 7 socket.close(); 8 return true; 9 10 return false;11 }12 13 }
connect这个方法,没错就是这个方法可以判断端口是否打开,后面我用了阻塞连接,timeout设置了15如果连接不上就返回fasle一旦连接上了就返回true,在线程里面可以看到返回true就调用了一个onSeepIP的方法,这个是什么了,其实这个是写了一个供外部访问的接口,已经和这个需求没有多大关系了。另外在附上调取的Demo,如果能帮到大家就再好不过了。
1 2 public void setOnSeekListener(OnSeekIpListener listener){ 3 this.listener = listener; 4 } 5 6 private void onSeekIp(String ip){ 7 if( listener != null){ 8 listener.onSeekIp(ip); 9 }10 };
这些还是写在这个类里面的,OnSeekIPListener 是从新定义了一个接口类,里面只有一个简单的方法:
1 public interface OnSeekIpListener {2 3 public void onSeekIp(String ip);4 5 }
到这里这个可供外部调用的的 寻找服务器IP的需求已经完成了。下来些一个简单的Demo来调用接口:
1 public class MainActivity extends Activity { 2 3 String date ; 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 // TODO Auto-generated method stub 7 8 super.onCreate(savedInstanceState); 9 UDPClient udpClient = new UDPClient();10 udpClient.setOnSeekListener(new UDPSeekListenner());11 udpClient.scan(6666);12 }13 14 class UDPSeekListenner implements OnSeekIpListener {15 16 @Override17 public void onSeekIp(String ip) {18 Log.e("UDP", "demo server_ip:"+ip);19 20 }21 }22 }
至此,所有流程已经完毕,还请各位大大轻喷。
在局域网中通过端口号扫描服务器IP