读书人

怎么快速扫描局域网内所有IP的某一个端

发布时间: 2012-08-08 14:32:45 作者: rapoo

如何快速扫描局域网内所有IP的某一个端口是否开启
例如:

本机IP: 123.333.222.10

需要扫描 IP: 123.333.222.1:6610 - 123.333.222.224:6610 判断端口是否开启 或者说是否有server在监听这个端口

请问如何快速(1秒内)完成上面的224个执行(from 1 to 224)

我自己贴一段代码 可以用是可以用 但是太慢了
本来想用

Java code
ExecutorService executor = Executors.newSingleThreadExecutor();executor.invokeAll(Arrays.asList(new Task(ipHead, tail, 6610)),200, TimeUnit.MILLISECONDS);executor.shutdown();

来提到效率的 但是好像没用 不知道是什么问题


runnable code:

Java code
import java.net.*;import java.util.Arrays;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import java.io.*;public class JPortScanner1 {    public JPortScanner1(String IP, int port) {    }    public static void main(String[] args) throws IOException,            InterruptedException {        String ipHead;        int lastPoint;        String IP = InetAddress.getLocalHost().getHostAddress();        lastPoint = IP.lastIndexOf('.');        ipHead = IP.substring(0, ++lastPoint);        for (int tail = 234; tail < 255; tail++) {            ExecutorService executor = Executors.newSingleThreadExecutor();            executor.invokeAll(Arrays.asList(new Task(ipHead, tail, 6610)),                    200, TimeUnit.MILLISECONDS);            executor.shutdown();        }    }}class Task implements Callable<String> {    String ipHead;    int ipTail;    int port;    public Task(String ipHead, int ipTail, int port) {        this.ipHead = ipHead;        this.ipTail = ipTail;        this.port = port;    }    public String call() throws Exception {        Socket connect = new Socket();        connect.setSoTimeout(100);            try {                            connect = new Socket(this.ipHead + ipTail, this.port);                connect.close();                System.out.println("Open port:" + this.ipHead + ipTail + " "                        + this.port);            } catch (UnknownHostException e) {                System.out.println("Unknown Port:" + this.ipHead + ipTail + " "                        + this.port);            } catch (IOException e) {                System.out.println("Unknown Port:" + this.ipHead + ipTail + " "                        + this.port);            }                 System.out.println("Finished!");        return null;    }}



[解决办法]
不动手无说服力(并不说我是个高手,只是想说怎么这么多人不去思考动手呢)
我测试的一个示例也就200多微妙(双核CPU):
Java code
import java.io.IOException;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.Socket;import java.net.UnknownHostException;import java.util.Collection;import java.util.LinkedList;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class JPortScanner1 {    public static void main(String[] args) throws InterruptedException, UnknownHostException {        String ipHead;        int lastPoint;        String IP = InetAddress.getLocalHost().getHostAddress();        lastPoint = IP.lastIndexOf('.');        ipHead = IP.substring(0, ++lastPoint);        ExecutorService executor = Executors.newCachedThreadPool();        Collection<Callable<String>> list = new LinkedList<Callable<String>>();        long start = System.currentTimeMillis();        for (int tail = 1; tail < 255; tail++) {            list.add(new Task(ipHead, tail, 8081));        }        executor.invokeAll(list);        executor.shutdown();        long end = System.currentTimeMillis();        System.out.println("All time: " + (end - start) + " milliseconds");    }}class Task implements Callable<String> {    String ipHead;    int ipTail;    int port;    public Task(String ipHead, int ipTail, int port) {        this.ipHead = ipHead;        this.ipTail = ipTail;        this.port = port;        System.out.println(ipHead + ipTail + ":" + port);    }    public String call(){        Socket connect = new Socket();        try {            connect.connect(new InetSocketAddress(ipHead + ipTail, port), 100);             while(true){                    if(connect.isConnected()){                        //System.out.println(ipHead + ipTail + ":" + port + " success");                        break;                    }                }                connect.close();        } catch (IOException e) {            //System.out.println(ipHead + ipTail + ":" + port + " failure");        }        return null;    }} 


[解决办法]
大哥,你的线程池怎么放到循环里面去了???
[解决办法]

探讨
引用:

我测试是在一个局域网段,在查看我本机的一些监听端口时8081是开启的,所以猜想其他人的机子也许会同样的监听此端口,当然也并不是所得IP地址是有效的,有效IP也不一定会开启8081这个端口。再者,我也是只是稍微修改了你原来的代码,并没有什么不能理解的地方;如果你要确认某台服务器是否开启某个端口,你可以用命令telnet直接测试下。

测试代码的话,……

[解决办法]
探讨
引用:
实际你可以把255分成5次,50个线程池,等一组全部运行完成了再下一组。50个线程一起应该不算多吧。我觉得100个都不算多。

50个线程没什么问题,但是50个tcp连接占用的资源就比较大了。

[解决办法]
其实应该和程序编写无关。楼主你现在是想要用UDP协议来测试还是TCP协议来测试呢?
若你要用UDP基本可以群发给各个主机去测试;但在目的机器上必须要有客户端程序进行接收和回复信息。
但你用TCP协议不可能快的;因为TCP通信协议就会复杂以及一些安全考虑(半连接处理和限制)。优点就是不需要在目的机器上安装测试程序。

若你觉得多线程去发送信息的效果不理想,TCP协议群发效果也不会有太大提升。
[解决办法]
传统的TCP链接扫描是最傻一种, 而且消耗CPU资源,相应的时间还跟网络带宽资源有一定的关系。
Java没有提供基于IP层的编程接口,无法实现TCP半开/半闭扫描,前面有提到Nmap

Nmap提供了非常全的TCP扫描方式,基础指纹栈识别技术,通过TCP扫描来识别操作系统,进而发现
系统漏洞,为下一步入侵系统探路。


[解决办法]
Java code
package net;import java.io.IOException;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.SocketAddress;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Set;public class JPortScannerByNIO {    public static void main(String[] args) throws IOException {        int port = 80;        int retry = 10;// 重试次数        String ip = InetAddress.getLocalHost().getHostAddress();        String ipHead = ip.substring(0, ip.lastIndexOf('.') + 1);        Selector selector = Selector.open();        for (int tail = 60; tail < 65; tail++) {            SocketChannel channel = SocketChannel.open();            SocketAddress address = new InetSocketAddress(ipHead + tail, port);            channel.configureBlocking(false);            channel.connect(address);            channel.register(selector, SelectionKey.OP_CONNECT, address);// 这里你也可以用输入或者输出        }        while (retry-- > 0) {            // selector.select(1000 * 5);这里可以设置超时时间            selector.select();            Set<SelectionKey> keys = selector.selectedKeys();            for (Iterator<SelectionKey> it = keys.iterator(); it.hasNext();) {                SelectionKey key = it.next();                it.remove();                if (key.isConnectable()) {                    System.err.println(key.attachment());                    key.cancel();                }            }        }    }}
[解决办法]
..明明是两只胖熊嘛...

注释上已经写明了一些参数的作用 比如你可以通过设置重试次数以及等待时间把程序的执行时间限制死 别的我就没啥办法了

读书人网 >J2SE开发

热点推荐