Java网络编程实现的简单端口扫描器示例

时间:2021-09-06 17:42:47

本文实例讲述了java网络编程实现的简单端口扫描器。分享给大家供大家参考,具体如下:

在计算机网络的学习中,不由得觉得这门课的零碎知识点异常之多,同时因为学习的课本是老外的教材——自顶向下方法,因此学习起来不免觉得吃力,但是从老外的教材里更能从一定高度理解计算机网络的知识体系,也是乐在其中,同时做英语的习题感觉也很有趣味,从各方面来说可以说是获益良多,认识了很多专业词汇。节课之后,便想做一个简单的端口扫描器,用的语言是java,因为实现界面很简单,同时也有封装好的socket类可以使用,主要思路如下:

在主程序界面里输入指定主机名或ip地址,按下start按钮,就可以扫描主机的常用端口是否打开。内部设置了常用端口号: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。也可以自行修改。程序实现原理就是利用java建立socket去连接目标ip的指定端口,如果能连接上就证明该端口开放。反之,若在超时之前都没有连接上,则该端口是关闭的,同时会产生异常。同时考虑到单线程操作效率较低,也利用了java可以多线程编程的特点,使用了多线程扫描目标主机的一个端口是否开放,因此最终显示结果中端口的排列顺序是随机的,且内部设定最多同时运行10个线程(可以根据实际情况更改)。

主要运用的网络知识就是套接字的使用。以及java内部的list容器,java的界面设计,界面布局,以及简单的泛型编程的用法。

主要代码如下:

?
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import java.awt.borderlayout;
import java.awt.color;
import java.awt.font;
import java.awt.gridlayout;
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
import java.io.ioexception;
import java.net.inetaddress;
import java.net.inetsocketaddress;
import java.net.socket;
import java.net.socketaddress;
import java.net.unknownhostexception;
import java.util.arrays;
import java.util.linkedlist;
import java.util.list;
import java.util.concurrent.executorservice;
import java.util.concurrent.executors;
import javax.swing.borderfactory;
import javax.swing.jbutton;
import javax.swing.jframe;
import javax.swing.jlabel;
import javax.swing.jpanel;
import javax.swing.jscrollpane;
import javax.swing.jtextarea;
import javax.swing.jtextfield;
public class scanport extends jframe {
 /**
  * 端口扫描启动主程序
  */
 private static final long serialversionuid = 1l;
 string str1 = " 常见端口有:";
 string str2 = "ftp:21,22,telnet:23,smtp:25,http:80";
 string str3 = "dns:53,tftp:69,snmp:161,162";
 string str4 = "1158,1433,1521,2100,3128,26,69";
 string str5 = "3306,3389,7001,8080,8081,110,143";
 string str6 = "9080,9090,43958,443,465,995,1080";
 jbutton jb1 = new jbutton("strat");
 jtextarea jta = new jtextarea();
 jscrollpane jsp = new jscrollpane(jta);
 jtextfield jtf = new jtextfield(17);
 string ip = "";//待扫描ip或域名
 list <integer>portlist = new linkedlist<integer>();// 定义一个list容器表示扫描的团口的list集合
 integer[] ports = new integer[] { 21, 22, 23, 25, 26, 53,69, 80, 110, 143,
   443,465,69,161,162,135,995,1080,1158,1433,1521,2100, 3128, 3306, 3389,
   7001, 8080, 8081, 9080, 9090, 43958 ,135,445,1025,1026,1027,1028,1055,5357};
 // 常见端口集合
 public scanport() {
  this.add(getpanel(), borderlayout.south);
  jsp.setborder(borderfactory.createetchedborder());
  jsp.setbackground(color.cyan);
  this.add(jsp, borderlayout.center);
  this.add(getpanel2(), borderlayout.north);
  this.add(getpanel3(), borderlayout.west);
  this.setbounds(300, 60, 600, 600);
  this.setdefaultcloseoperation(jframe.exit_on_close);
  this.settitle("scanport");
  jta.settabsize(4);
  jta.setfont(new font("标楷体", font.bold, 16));
  jta.setlinewrap(true);// 激活自动换行功能
  jta.setwrapstyleword(true);// 激活断行不断字功能
  portlist.addall(arrays.aslist(ports));
  //将ports中的值加入到set中,并去掉重复的
  jb1.addactionlistener(new actionlistener() {
   @override
   public void actionperformed(actionevent e) {
    // todo auto-generated method stub
    ip = jta.gettext();
    //ip为文本框内输入的字符串
    scanports(ip, portlist, 10, 800);
    //超时时间设定为800,线程数设定为10
   }
  });
  this.setvisible(true);
 }
 /**
  * 多线程扫描目标主机指定list端口集合的开放情况
  *
  * @param ip
  *   待扫描ip或域名
  * @param portlist
  *   待扫描的端口的list集合
  * @param threadnumber
  *   线程数
  * @param timeout
  *   连接超时时间
  * */
 public void scanports(string ip, list<integer> portset,int threadnumber, int timeout) {
  executorservice threadpool = executors.newcachedthreadpool();
  //线程池
  for (int i = 0; i < threadnumber; i++) {
   //10个线程 加入到线程池里
   scanmethod scanmethod2 = new scanmethod(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();
   }
  }// end of while
 }
 /*
  * 扫描方式:针对一个待扫描的端口的list集合进行扫描
  */
 private class scanmethod implements runnable {
  private string ip; // 目标ip
  private list<integer> portlist; // 待扫描的端口的list集合
  private int threadnumber, serial, timeout; // 线程数,这是第几个线程,超时时间
  public scanmethod(string ip, list<integer> portlist, int threadnumber,int serial, int timeout) {
   this.ip = ip;
   this.portlist = portlist;
   this.threadnumber = threadnumber;
   this.serial = serial;
   this.timeout = timeout;
  }
  public void run() {
   int port = 0;
   integer[] ports = portlist.toarray(new integer[portlist.size()]); // list转数组
   try {
    inetaddress address = inetaddress.getbyname(ip); //如果输入的是主机名,尝试获取ip地址
    socket socket;//定义套接字
    socketaddress socketaddress;//传递ip和端口
    if (ports.length < 1)
     //若数组没有元素,返回,不执行
     return;
    for (port = 0 + serial; port <= ports.length - 1; port += threadnumber) {
     //每次运行10个线程
     socket = new socket();
     //为对象分配内存空间
     socketaddress = new inetsocketaddress(address, ports[port]);
     try {
      socket.connect(socketaddress, timeout);
      //对目标主机的指定端口进行连接,超时后连接失败
      socket.close();
      //关闭端口
      system.out.println("端口 " + ports[port] + " :开放");
      jta.append("端口 " + ports[port] + " :开放\n");
      //在文本区域里更新消息
     } catch (ioexception e) {
      system.out.println("端口 " + ports[port] + " :关闭");
      jta.append("端口 " + ports[port] + " :关闭\n");
      //产生异常表示端口关闭
     }
    }
   } catch (unknownhostexception e) {
    e.printstacktrace();
   }
  }
  //end of run()
 }//end of scanmethod
 public jpanel getpanel() {
  jpanel jp = new jpanel();
  jp.add(jb1, borderlayout.center);
  jp.setborder(borderfactory.createraisedbevelborder());
  jp.setbackground(color.lightgray);
  return jp;
 }
 public jpanel getpanel2() {
  jpanel jp = new jpanel();
  jlabel jl = new jlabel();
  jl.settext("请输入主机名或ip地址,将扫描该主机的常见端口号:");
  jp.add(jl);
  jp.add(jtf);
  jp.setborder(borderfactory.createraisedbevelborder());
  jp.setbackground(color.light_gray);
  return jp;
 }
 public jpanel getpanel3() {
  jlabel jl1 = new jlabel(str1);
  jlabel jl2 = new jlabel(str2);
  jlabel jl3 = new jlabel(str3);
  jlabel jl4 = new jlabel(str4);
  jlabel jl5 = new jlabel(str5);
  jlabel jl6 = new jlabel(str6);
  jpanel jp = new jpanel();
  jp.setlayout(new gridlayout(6, 1));
  jp.add(jl1);
  jp.add(jl2);
  jp.add(jl3);
  jp.add(jl4);
  jp.add(jl5);
  jp.add(jl6);
  jp.setborder(borderfactory.createetchedborder());
  //蚀刻边框
  return jp;
 }
 public static void main(string[] args) {
  new scanport();
 }
}

希望本文所述对大家java程序设计有所帮助。

原文链接:https://blog.csdn.net/wangbowj123/article/details/76473065