本文實(shí)例講述了java網(wǎng)絡(luò)編程實(shí)現(xiàn)的簡(jiǎn)單端口掃描器。分享給大家供大家參考,具體如下:
在計(jì)算機(jī)網(wǎng)絡(luò)的學(xué)習(xí)中,不由得覺得這門課的零碎知識(shí)點(diǎn)異常之多,同時(shí)因?yàn)閷W(xué)習(xí)的課本是老外的教材——自頂向下方法,因此學(xué)習(xí)起來不免覺得吃力,但是從老外的教材里更能從一定高度理解計(jì)算機(jī)網(wǎng)絡(luò)的知識(shí)體系,也是樂在其中,同時(shí)做英語的習(xí)題感覺也很有趣味,從各方面來說可以說是獲益良多,認(rèn)識(shí)了很多專業(yè)詞匯。節(jié)課之后,便想做一個(gè)簡(jiǎn)單的端口掃描器,用的語言是java,因?yàn)閷?shí)現(xiàn)界面很簡(jiǎn)單,同時(shí)也有封裝好的socket類可以使用,主要思路如下:
在主程序界面里輸入指定主機(jī)名或ip地址,按下start按鈕,就可以掃描主機(jī)的常用端口是否打開。內(nèi)部設(shè)置了常用端口號(hào):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。也可以自行修改。程序?qū)崿F(xiàn)原理就是利用java建立socket去連接目標(biāo)ip的指定端口,如果能連接上就證明該端口開放。反之,若在超時(shí)之前都沒有連接上,則該端口是關(guān)閉的,同時(shí)會(huì)產(chǎn)生異常。同時(shí)考慮到單線程操作效率較低,也利用了java可以多線程編程的特點(diǎn),使用了多線程掃描目標(biāo)主機(jī)的一個(gè)端口是否開放,因此最終顯示結(jié)果中端口的排列順序是隨機(jī)的,且內(nèi)部設(shè)定最多同時(shí)運(yùn)行10個(gè)線程(可以根據(jù)實(shí)際情況更改)。
主要運(yùn)用的網(wǎng)絡(luò)知識(shí)就是套接字的使用。以及java內(nèi)部的list容器,java的界面設(shè)計(jì),界面布局,以及簡(jiǎn)單的泛型編程的用法。
主要代碼如下:
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 { /** * 端口掃描啟動(dòng)主程序 */ 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>(); // 定義一個(gè)list容器表示掃描的團(tuán)口的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( "標(biāo)楷體" , font.bold, 16 )); jta.setlinewrap( true ); // 激活自動(dòng)換行功能 jta.setwrapstyleword( true ); // 激活斷行不斷字功能 portlist.addall(arrays.aslist(ports)); //將ports中的值加入到set中,并去掉重復(fù)的 jb1.addactionlistener( new actionlistener() { @override public void actionperformed(actionevent e) { // todo auto-generated method stub ip = jta.gettext(); //ip為文本框內(nèi)輸入的字符串 scanports(ip, portlist, 10 , 800 ); //超時(shí)時(shí)間設(shè)定為800,線程數(shù)設(shè)定為10 } }); this .setvisible( true ); } /** * 多線程掃描目標(biāo)主機(jī)指定list端口集合的開放情況 * * @param ip * 待掃描ip或域名 * @param portlist * 待掃描的端口的list集合 * @param threadnumber * 線程數(shù) * @param timeout * 連接超時(shí)時(shí)間 * */ public void scanports(string ip, list<integer> portset, int threadnumber, int timeout) { executorservice threadpool = executors.newcachedthreadpool(); //線程池 for ( int i = 0 ; i < threadnumber; i++) { //10個(gè)線程 加入到線程池里 scanmethod scanmethod2 = new scanmethod(ip, portset,threadnumber, i, timeout); threadpool.execute(scanmethod2); } threadpool.shutdown(); while ( true ) { if (threadpool.isterminated()) { system.out.println( "掃描結(jié)束" ); break ; } try { thread.sleep( 1000 ); } catch (interruptedexception e) { e.printstacktrace(); } } // end of while } /* * 掃描方式:針對(duì)一個(gè)待掃描的端口的list集合進(jìn)行掃描 */ private class scanmethod implements runnable { private string ip; // 目標(biāo)ip private list<integer> portlist; // 待掃描的端口的list集合 private int threadnumber, serial, timeout; // 線程數(shù),這是第幾個(gè)線程,超時(shí)時(shí)間 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轉(zhuǎn)數(shù)組 try { inetaddress address = inetaddress.getbyname(ip); //如果輸入的是主機(jī)名,嘗試獲取ip地址 socket socket; //定義套接字 socketaddress socketaddress; //傳遞ip和端口 if (ports.length < 1 ) //若數(shù)組沒有元素,返回,不執(zhí)行 return ; for (port = 0 + serial; port <= ports.length - 1 ; port += threadnumber) { //每次運(yùn)行10個(gè)線程 socket = new socket(); //為對(duì)象分配內(nèi)存空間 socketaddress = new inetsocketaddress(address, ports[port]); try { socket.connect(socketaddress, timeout); //對(duì)目標(biāo)主機(jī)的指定端口進(jìn)行連接,超時(shí)后連接失敗 socket.close(); //關(guān)閉端口 system.out.println( "端口 " + ports[port] + " :開放" ); jta.append( "端口 " + ports[port] + " :開放\n" ); //在文本區(qū)域里更新消息 } catch (ioexception e) { system.out.println( "端口 " + ports[port] + " :關(guān)閉" ); jta.append( "端口 " + ports[port] + " :關(guān)閉\n" ); //產(chǎn)生異常表示端口關(guā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( "請(qǐng)輸入主機(jī)名或ip地址,將掃描該主機(jī)的常見端口號(hào):" ); 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(); } } |
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
原文鏈接:https://blog.csdn.net/wangbowj123/article/details/76473065