java多线程实现端口扫描,使用Java开发多线程端口扫描工具
前言:這里只給出命令行版的掃描工具,后續可能是寫一個獨立的界面,或者是集成到其他工具上去。
一 掃描原理
其實原理非常簡單,就是使用Socket去連接目標IP或者域名的指定端口,如果能夠連上則說明該端口是打開的。反之,要是在連接超時之前都沒有連上,則將該端口判斷為關閉狀態。下面我將分別說明兩種基本的掃描方式:(1)掃描一個連續的端口段;(2)僅掃描一個指定的端口集合
二 使用多線程掃描目標主機一個段的端口開放情況
/**
* 多線程掃描目標主機一個段的端口開放情況
*
* @param ip
* 待掃描IP或域名,eg:180.97.161.184 www.zifangsky.cn
* @param startPort
* 起始端口
* @param endPort
* 結束端口
* @param threadNumber
* 線程數
* @param timeout
* 連接超時時間
* */
public void scanLargePorts(String ip, int startPort, int endPort,
int threadNumber, int timeout) {
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 0; i < threadNumber; i++) {
ScanMethod1 scanMethod1 = new ScanMethod1(ip, startPort, endPort,
threadNumber, i, timeout);
threadPool.execute(scanMethod1);
}
threadPool.shutdown();
// 每秒中查看一次是否已經掃描結束
while (true) {
if (threadPool.isTerminated()) {
System.out.println("掃描結束");
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36/**
* 多線程掃描目標主機一個段的端口開放情況
*
* @param ip
*????????????待掃描IP或域名,eg:180.97.161.184 www.zifangsky.cn
* @param startPort
*????????????起始端口
* @param endPort
*????????????結束端口
* @param threadNumber
*????????????線程數
* @param timeout
*????????????連接超時時間
* */
publicvoidscanLargePorts(Stringip,intstartPort,intendPort,
intthreadNumber,inttimeout){
ExecutorServicethreadPool=Executors.newCachedThreadPool();
for(inti=0;i
ScanMethod1scanMethod1=newScanMethod1(ip,startPort,endPort,
threadNumber,i,timeout);
threadPool.execute(scanMethod1);
}
threadPool.shutdown();
// 每秒中查看一次是否已經掃描結束
while(true){
if(threadPool.isTerminated()){
System.out.println("掃描結束");
break;
}
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
然后是一個內部類ScanMethod1實現了Runnable接口:
/**
* 掃描方式一:針對起始結束端口,進行逐個掃描
*
* */
class ScanMethod1 implements Runnable {
private String ip; // 目標IP
private int startPort, endPort, threadNumber, serial, timeout; // 起始和結束端口,線程數,這是第幾個線程,超時時間
/**
* 初始化
*
* @param ip
* 待掃描IP或域名
* @param startPort
* 起始端口
* @param endPort
* 結束端口
* @param threadNumber
* 線程數
* @param serial
* 標記是第幾個線程
* @param timeout
* 連接超時時間
* */
public ScanMethod1(String ip, int startPort, int endPort,
int threadNumber, int serial, int timeout) {
this.ip = ip;
this.startPort = startPort;
this.endPort = endPort;
this.threadNumber = threadNumber;
this.serial = serial;
this.timeout = timeout;
}
public void run() {
int port = 0;
try {
InetAddress address = InetAddress.getByName(ip);
Socket socket;
SocketAddress socketAddress;
for (port = startPort + serial; port <= endPort; port += threadNumber) {
socket = new Socket();
socketAddress = new InetSocketAddress(address, port);
try {
socket.connect(socketAddress, timeout); // 超時時間
socket.close();
System.out.println("端口 " + port + " :開放");
} catch (IOException e) {
// System.out.println("端口 " + port + " :關閉");
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57/**
* 掃描方式一:針對起始結束端口,進行逐個掃描
*
* */
classScanMethod1implementsRunnable{
privateStringip;// 目標IP
privateintstartPort,endPort,threadNumber,serial,timeout;// 起始和結束端口,線程數,這是第幾個線程,超時時間
/**
* 初始化
*
* @param ip
*????????????待掃描IP或域名
* @param startPort
*????????????起始端口
* @param endPort
*????????????結束端口
* @param threadNumber
*????????????線程數
* @param serial
*????????????標記是第幾個線程
* @param timeout
*????????????連接超時時間
* */
publicScanMethod1(Stringip,intstartPort,intendPort,
intthreadNumber,intserial,inttimeout){
this.ip=ip;
this.startPort=startPort;
this.endPort=endPort;
this.threadNumber=threadNumber;
this.serial=serial;
this.timeout=timeout;
}
publicvoidrun(){
intport=0;
try{
InetAddressaddress=InetAddress.getByName(ip);
Socketsocket;
SocketAddresssocketAddress;
for(port=startPort+serial;port<=endPort;port+=threadNumber){
socket=newSocket();
socketAddress=newInetSocketAddress(address,port);
try{
socket.connect(socketAddress,timeout);// 超時時間
socket.close();
System.out.println("端口 "+port+" :開放");
}catch(IOExceptione){
// System.out.println("端口 " + port + " :關閉");
}
}
}catch(UnknownHostExceptione){
e.printStackTrace();
}
}
}
三 使用多線程掃描目標主機指定Set端口集合的開放情況
/**
* 多線程掃描目標主機指定Set端口集合的開放情況
*
* @param ip
* 待掃描IP或域名,eg:180.97.161.184 www.zifangsky.cn
* @param portSet
* 待掃描的端口的Set集合
* @param threadNumber
* 線程數
* @param timeout
* 連接超時時間
* */
public void scanLargePorts(String ip, Set portSet,
int threadNumber, int timeout) {
ExecutorService threadPool = Executors.newCachedThreadPool();
for (int i = 0; i < threadNumber; i++) {
ScanMethod2 scanMethod2 = new ScanMethod2(ip, portSet,
threadNumber, i, timeout);
threadPool.execute(scanMethod2);
}
threadPool.shutdown();
while (true) {
if (threadPool.isTerminated()) {
System.out.println("掃描結束");
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33/**
* 多線程掃描目標主機指定Set端口集合的開放情況
*
* @param ip
*????????????待掃描IP或域名,eg:180.97.161.184 www.zifangsky.cn
* @param portSet
*????????????待掃描的端口的Set集合
* @param threadNumber
*????????????線程數
* @param timeout
*????????????連接超時時間
* */
publicvoidscanLargePorts(Stringip,SetportSet,
intthreadNumber,inttimeout){
ExecutorServicethreadPool=Executors.newCachedThreadPool();
for(inti=0;i
ScanMethod2scanMethod2=newScanMethod2(ip,portSet,
threadNumber,i,timeout);
threadPool.execute(scanMethod2);
}
threadPool.shutdown();
while(true){
if(threadPool.isTerminated()){
System.out.println("掃描結束");
break;
}
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
具體的線程內部類跟上面類似,代碼如下:
/**
* 掃描方式二:針對一個待掃描的端口的Set集合進行掃描
*
* */
private class ScanMethod2 implements Runnable {
private String ip; // 目標IP
private Set portSet; // 待掃描的端口的Set集合
private int threadNumber, serial, timeout; // 線程數,這是第幾個線程,超時時間
public ScanMethod2(String ip, Set portSet, int threadNumber,
int serial, int timeout) {
this.ip = ip;
this.portSet = portSet;
this.threadNumber = threadNumber;
this.serial = serial;
this.timeout = timeout;
}
public void run() {
int port = 0;
Integer[] ports = portSet.toArray(new Integer[portSet.size()]); // Set轉數組
try {
InetAddress address = InetAddress.getByName(ip);
Socket socket;
SocketAddress socketAddress;
if (ports.length < 1)
return;
for (port = 0 + serial; port <= ports.length - 1; port += threadNumber) {
socket = new Socket();
socketAddress = new InetSocketAddress(address, ports[port]);
try {
socket.connect(socketAddress, timeout);
socket.close();
System.out.println("端口 " + ports[port] + " :開放");
} catch (IOException e) {
// System.out.println("端口 " + ports[port] + " :關閉");
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45/**
* 掃描方式二:針對一個待掃描的端口的Set集合進行掃描
*
* */
privateclassScanMethod2implementsRunnable{
privateStringip;// 目標IP
privateSetportSet;// 待掃描的端口的Set集合
privateintthreadNumber,serial,timeout;// 線程數,這是第幾個線程,超時時間
publicScanMethod2(Stringip,SetportSet,intthreadNumber,
intserial,inttimeout){
this.ip=ip;
this.portSet=portSet;
this.threadNumber=threadNumber;
this.serial=serial;
this.timeout=timeout;
}
publicvoidrun(){
intport=0;
Integer[]ports=portSet.toArray(newInteger[portSet.size()]);// Set轉數組
try{
InetAddressaddress=InetAddress.getByName(ip);
Socketsocket;
SocketAddresssocketAddress;
if(ports.length<1)
return;
for(port=0+serial;port<=ports.length-1;port+=threadNumber){
socket=newSocket();
socketAddress=newInetSocketAddress(address,ports[port]);
try{
socket.connect(socketAddress,timeout);
socket.close();
System.out.println("端口 "+ports[port]+" :開放");
}catch(IOExceptione){
// System.out.println("端口 " + ports[port] + " :關閉");
}
}
}catch(UnknownHostExceptione){
e.printStackTrace();
}
}
}
四兩種掃描方式的測試用例
public static void main(String[] args) {
PortScanDemo portScanDemo = new PortScanDemo();
//方式1
// portScanDemo.scanLargePorts("ultra-book.co", 20, 10000, 5,800);
// portScanDemo.scanLargePorts("180.97.161.184", 1, 100, 5);
//方式2
Set portSet = new LinkedHashSet();
Integer[] ports = new Integer[] { 21, 22, 23, 25, 26, 69, 80, 110, 143,
443, 465, 995, 1080, 1158, 1433, 1521, 2100, 3128, 3306, 3389,
7001, 8080, 8081, 9080, 9090,43958};
portSet.addAll(Arrays.asList(ports));
portScanDemo.scanLargePorts("ultra-book.co", portSet, 5, 800);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15publicstaticvoidmain(String[]args){
PortScanDemoportScanDemo=newPortScanDemo();
//方式1
// portScanDemo.scanLargePorts("ultra-book.co", 20, 10000, 5,800);
// portScanDemo.scanLargePorts("180.97.161.184", 1, 100, 5);
//方式2
SetportSet=newLinkedHashSet();
Integer[]ports=newInteger[]{21,22,23,25,26,69,80,110,143,
443,465,995,1080,1158,1433,1521,2100,3128,3306,3389,
7001,8080,8081,9080,9090,43958};
portSet.addAll(Arrays.asList(ports));
portScanDemo.scanLargePorts("ultra-book.co",portSet,5,800);
}
五測試結果
注:1 超時時間是以毫秒為單位,其中要是掃描國內的IP可以把這個時間適當設置低一點,200~500左右。相反,要是掃描國外IP就需要把這個時間適當設置大一點,不然有可能把本來打開的端口也漏掉了
總結
以上是生活随笔為你收集整理的java多线程实现端口扫描,使用Java开发多线程端口扫描工具的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xd中国重工什么意思
- 下一篇: 工行房贷宽限期