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,List portSet,intthreadNumber,inttimeout){ ExecutorServicethreadPool=Executors.newCachedThreadPool(); //线程池 for(inti=0;i portList;//待扫描的端口的List集合 privateintthreadNumber,serial,timeout;//线程数,这是第几个线程,超时时间 publicScanMethod(Stringip,List portList,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程序设计有所帮助。