欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-11-26 20:12:40
本文实例讲述了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的界面设计,界面布局,以及简单的泛型编程的用法。

主要代码如下:

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相关内容感兴趣的读者可查看本站专题:《java网络编程技巧总结》、《java socket编程技巧总结》、《java文件与目录操作技巧汇总》、《java数据结构与算法教程》、《java操作dom节点技巧总结》和《java缓存操作技巧汇总

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