Java網(wǎng)絡編程實現(xiàn)的簡單端口掃描器示例
本文實例講述了Java網(wǎng)絡編程實現(xiàn)的簡單端口掃描器。分享給大家供大家參考,具體如下:
在計算機網(wǎng)絡的學習中,不由得覺得這門課的零碎知識點異常之多,同時因為學習的課本是老外的教材——自頂向下方法,因此學習起來不免覺得吃力,但是從老外的教材里更能從一定高度理解計算機網(wǎng)絡的知識體系,也是樂在其中,同時做英語的習題感覺也很有趣味,從各方面來說可以說是獲益良多,認識了很多專業(yè)詞匯。節(jié)課之后,便想做一個簡單的端口掃描器,用的語言是java,因為實現(xiàn)界面很簡單,同時也有封裝好的Socket類可以使用,主要思路如下:
在主程序界面里輸入指定主機名或ip地址,按下start按鈕,就可以掃描主機的常用端口是否打開。內(nèi)部設置了常用端口號: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。也可以自行修改。程序實現(xiàn)原理就是利用Java建立Socket去連接目標ip的指定端口,如果能連接上就證明該端口開放。反之,若在超時之前都沒有連接上,則該端口是關閉的,同時會產(chǎn)生異常。同時考慮到單線程操作效率較低,也利用了Java可以多線程編程的特點,使用了多線程掃描目標主機的一個端口是否開放,因此最終顯示結果中端口的排列順序是隨機的,且內(nèi)部設定最多同時運行10個線程(可以根據(jù)實際情況更改)。
主要運用的網(wǎng)絡知識就是套接字的使用。以及java內(nèi)部的List容器,java的界面設計,界面布局,以及簡單的泛型編程的用法。
主要代碼如下:
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為文本框內(nèi)輸入的字符串
scanPorts(IP, portList, 10, 800);
//超時時間設定為800,線程數(shù)設定為10
}
});
this.setVisible(true);
}
/**
* 多線程掃描目標主機指定List端口集合的開放情況
*
* @param ip
* 待掃描IP或域名
* @param portList
* 待掃描的端口的List集合
* @param threadNumber
* 線程數(shù)
* @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; // 線程數(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轉數(shù)組
try {
InetAddress address = InetAddress.getByName(ip); //如果輸入的是主機名,嘗試獲取ip地址
Socket socket;//定義套接字
SocketAddress socketAddress;//傳遞ip和端口
if (ports.length < 1)
//若數(shù)組沒有元素,返回,不執(zhí)行
return;
for (port = 0 + serial; port <= ports.length - 1; port += threadNumber) {
//每次運行10個線程
socket = new Socket();
//為對象分配內(nèi)存空間
socketAddress = new InetSocketAddress(address, ports[port]);
try {
socket.connect(socketAddress, timeout);
//對目標主機的指定端口進行連接,超時后連接失敗
socket.close();
//關閉端口
System.out.println("端口 " + ports[port] + " :開放");
jta.append("端口 " + ports[port] + " :開放\n");
//在文本區(qū)域里更新消息
} catch (IOException e) {
System.out.println("端口 " + ports[port] + " :關閉");
jta.append("端口 " + ports[port] + " :關閉\n");
//產(chǎ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相關內(nèi)容感興趣的讀者可查看本站專題:《Java網(wǎng)絡編程技巧總結》、《Java Socket編程技巧總結》、《Java文件與目錄操作技巧匯總》、《Java數(shù)據(jù)結構與算法教程》、《Java操作DOM節(jié)點技巧總結》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設計有所幫助。
相關文章
SpringBoot開發(fā)項目,引入JPA找不到findOne方法的解決
這篇文章主要介紹了SpringBoot開發(fā)項目,引入JPA找不到findOne方法的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
Java開發(fā)反射機制的實戰(zhàn)經(jīng)驗總結
反射是java中一種強大的工具,能夠使我們很方便的創(chuàng)建靈活的代碼,這些代碼可以再運行時裝配,無需在組件之間進行源代碼鏈接,但是反射使用不當會成本很高,這篇文章主要給大家介紹了關于Java開發(fā)反射機制的相關資料,需要的朋友可以參考下2021-07-07
用SpringBoot框架來接收multipart/form-data文件方式
這篇文章主要介紹了用SpringBoot框架來接收multipart/form-data文件方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
SpringCloud實戰(zhàn)小貼士之Zuul的路徑匹配
這篇文章主要介紹了SpringCloud實戰(zhàn)小貼士之Zuul的路徑匹配,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10

