Java网络编程实现的简单端口扫描器示例
本文实例讲述了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的界面设计,界面布局,以及简单的泛型编程的用法。
主要代码如下:
importjava.awt.BorderLayout;
importjava.awt.Color;
importjava.awt.Font;
importjava.awt.GridLayout;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.io.IOException;
importjava.net.InetAddress;
importjava.net.InetSocketAddress;
importjava.net.Socket;
importjava.net.SocketAddress;
importjava.net.UnknownHostException;
importjava.util.Arrays;
importjava.util.LinkedList;
importjava.util.List;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importjavax.swing.BorderFactory;
importjavax.swing.JButton;
importjavax.swing.JFrame;
importjavax.swing.JLabel;
importjavax.swing.JPanel;
importjavax.swing.JScrollPane;
importjavax.swing.JTextArea;
importjavax.swing.JTextField;
publicclassScanPortextendsJFrame{
/**
*端口扫描启动主程序
*/
privatestaticfinallongserialVersionUID=1L;
Stringstr1="常见端口有:";
Stringstr2="ftp:21,22,telnet:23,smtp:25,http:80";
Stringstr3="dns:53,tftp:69,snmp:161,162";
Stringstr4="1158,1433,1521,2100,3128,26,69";
Stringstr5="3306,3389,7001,8080,8081,110,143";
Stringstr6="9080,9090,43958,443,465,995,1080";
JButtonjb1=newJButton("strat");
JTextAreajta=newJTextArea();
JScrollPanejsp=newJScrollPane(jta);
JTextFieldjtf=newJTextField(17);
StringIP="";//待扫描IP或域名
ListportList=newLinkedList();//定义一个List容器表示扫描的团口的List集合
Integer[]ports=newInteger[]{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};
//常见端口集合
publicScanPort(){
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(newFont("标楷体",Font.BOLD,16));
jta.setLineWrap(true);//激活自动换行功能
jta.setWrapStyleWord(true);//激活断行不断字功能
portList.addAll(Arrays.asList(ports));
//将ports中的值加入到set中,并去掉重复的
jb1.addActionListener(newActionListener(){
@Override
publicvoidactionPerformed(ActionEvente){
//TODOAuto-generatedmethodstub
IP=jta.getText();
//ip为文本框内输入的字符串
scanPorts(IP,portList,10,800);
//超时时间设定为800,线程数设定为10
}
});
this.setVisible(true);
}
/**
*多线程扫描目标主机指定List端口集合的开放情况
*
*@paramip
*待扫描IP或域名
*@paramportList
*待扫描的端口的List集合
*@paramthreadNumber
*线程数
*@paramtimeout
*连接超时时间
**/
publicvoidscanPorts(Stringip,ListportSet,intthreadNumber,inttimeout){
ExecutorServicethreadPool=Executors.newCachedThreadPool();
//线程池
for(inti=0;iportList;//待扫描的端口的List集合
privateintthreadNumber,serial,timeout;//线程数,这是第几个线程,超时时间
publicScanMethod(Stringip,ListportList,intthreadNumber,intserial,inttimeout){
this.ip=ip;
this.portList=portList;
this.threadNumber=threadNumber;
this.serial=serial;
this.timeout=timeout;
}
publicvoidrun(){
intport=0;
Integer[]ports=portList.toArray(newInteger[portList.size()]);//List转数组
try{
InetAddressaddress=InetAddress.getByName(ip);//如果输入的是主机名,尝试获取ip地址
Socketsocket;//定义套接字
SocketAddresssocketAddress;//传递ip和端口
if(ports.length<1)
//若数组没有元素,返回,不执行
return;
for(port=0+serial;port<=ports.length-1;port+=threadNumber){
//每次运行10个线程
socket=newSocket();
//为对象分配内存空间
socketAddress=newInetSocketAddress(address,ports[port]);
try{
socket.connect(socketAddress,timeout);
//对目标主机的指定端口进行连接,超时后连接失败
socket.close();
//关闭端口
System.out.println("端口"+ports[port]+":开放");
jta.append("端口"+ports[port]+":开放\n");
//在文本区域里更新消息
}catch(IOExceptione){
System.out.println("端口"+ports[port]+":关闭");
jta.append("端口"+ports[port]+":关闭\n");
//产生异常表示端口关闭
}
}
}catch(UnknownHostExceptione){
e.printStackTrace();
}
}
//endofrun()
}//endofScanMethod
publicJPanelgetPanel(){
JPaneljp=newJPanel();
jp.add(jb1,BorderLayout.CENTER);
jp.setBorder(BorderFactory.createRaisedBevelBorder());
jp.setBackground(Color.lightGray);
returnjp;
}
publicJPanelgetPanel2(){
JPaneljp=newJPanel();
JLabeljl=newJLabel();
jl.setText("请输入主机名或ip地址,将扫描该主机的常见端口号:");
jp.add(jl);
jp.add(jtf);
jp.setBorder(BorderFactory.createRaisedBevelBorder());
jp.setBackground(Color.LIGHT_GRAY);
returnjp;
}
publicJPanelgetPanel3(){
JLabeljl1=newJLabel(str1);
JLabeljl2=newJLabel(str2);
JLabeljl3=newJLabel(str3);
JLabeljl4=newJLabel(str4);
JLabeljl5=newJLabel(str5);
JLabeljl6=newJLabel(str6);
JPaneljp=newJPanel();
jp.setLayout(newGridLayout(6,1));
jp.add(jl1);
jp.add(jl2);
jp.add(jl3);
jp.add(jl4);
jp.add(jl5);
jp.add(jl6);
jp.setBorder(BorderFactory.createEtchedBorder());
//蚀刻边框
returnjp;
}
publicstaticvoidmain(String[]args){
newScanPort();
}
}
更多关于java相关内容感兴趣的读者可查看本站专题:《Java网络编程技巧总结》、《JavaSocket编程技巧总结》、《Java文件与目录操作技巧汇总》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。