[网络安全课设]基于JAVA的系统端口扫描软件设计实现(java代码+IDEA+UI图形界面+实验报告)

链接::l基于JAVA的系统端口扫描软件设计实现(java代码+IDEA+UI图形界面+实验报告)

系统端口扫描软件设计实现

  • 设计目的和任务

参照superscan、nmap等端口扫描软件的运行情况,自行设计一个简单的端口扫描软件,能够根据TCP、IMCP等探测方法,探测目标主机开放的端口。

要求:

(1)用ping扫描测试目标主机的连通状态,若ping不通,则显示主机不在网络。

(2) 若ping可达,则设计程序对目标主机进行端口扫描,显示常见端口的扫描结果,识别目标操作系统类型。

(3)使用多线程实现能同时扫描多台主机。设计程序对IP地址(单个IP,一段IP范围)、指定主机名的端口(指定端口,所有端口)进行扫描,以获得相关的信息。

(4)友好地图形用户界面,扫描过程中能显示扫描进度,扫描时间,异常告警窗口(如IP地址范围出界等),在局域网段实现。

三、 实验环境和总体设计

实验环境:Window XP系统、java虚拟机、JDK1.8.1和IDEA.2021.1

总体设计:端口扫描系统分为两个界面,分别是用户登陆界面和功能界面。在用户登录界面中,设置了一个登陆的账号密码管理校检机制,使软件的使用更加严密、可靠;功能界面是由菜单栏,IP扫描,端口扫描和扫描结果等控件组成的一个完整简介,功能齐全的操作界面,充分的从用户感受出发,最大化满足用户的需求。

五、结果测试与分析

登陆界面:

  首先打开的是账户登陆界面,它由账号输入文本框,密码输入文本框,界面标题,最小化按钮,登录按钮和关闭按钮组成,背景颜色为灰白色,文本大小适中,字体为微软雅黑,居中。需要用户在文本框内输入正确的帐号和密码,再点击“登陆”按钮,与后台预设的账号密码进行比对,校检正确之后才能进入下操作界面。如果账号输入错误,会弹出错误警告窗口;如果密码输入错误,会弹出警告窗口。只有账号和密码输入正确,才能进入操作界面。

   

账号输入错误:        正确账号是“admin”

           密码输入错误:       正确密码是“123456”

                 

           验证成功:  

操作界面

  通过了安全性验证之后,就可以开始端口扫描操作。操作界面由标题,菜单栏,扫描方式选择(IP扫描,端口扫描),ip地址段输入框,端口号输入框,线程数输入框,开始扫描按钮,退出按钮,清空按钮,扫描结果显示区。根据用户的需求选择扫描的方式:对ip地址扫描或者扫描目的主机的端口号。如果选择的是ip地址扫描,还可以继续选择对单个ip地址进行扫描,或者对一段ip地址进行扫描,此外还会对输入的ip地址进行合法性检验,否则会显示ip输入错误警告;如果选择的是对端口扫描,首先需要输入目的主机的ip地址,通过ip地址合法性检验之后,再选择对常用端口扫描或者是指定端口扫描。软件支持多线程扫描,可以自定义最大线程数,利用多线程来提高端口扫描的时间效率。扫描结果会在操作页面的下半部分显示出扫描时间,ip地址是否可达,端口开放状态,目的主机操作系统类型。

   

扫描IP地址可能出现的异常:通过try-catch捕获异常

Ip地址输入合法性:

           Ip地址输入越界性:

                     

           Ip地址输入逻辑性:

扫描目的主机端口号可能出现的异常:通过try-catch捕获异常

       目的主机ip地址输入错误:

           端口号输入越界性:

                 

           端口号输入逻辑性:

                 

    多线程:通过java.util.concurrent.ExecutorService包生成一个固定数量的线程池,执行多线程服务:

ExecutorService executor = Executors.newFixedThreadPool(threadNum)

再通过executor.execute(new PingRunner())与threadPool.execute(scanMethod)开启多线程ping扫描和端口号扫描。

线程数输入合法性:

四、详细设计步骤

账户登陆模块:在用户登陆界面中,需要输入“账号”和“密码”,密码正确才能跳转到操作页面,否则不能进行扫描操作。

关键算法:

//用户名正确,比较密码,equals():比较字符串是否相等

if (username.getText().trim().equals("admin")) {// getText():得到输入的密码

boolean isCorrect = true;// trim()去掉字符串的首尾空格

char[] ch1 = pwd.getPassword();//ch1是用户输入的密码

char[] ch2 = s.toCharArray();//ch2是默认密码 

if (ch1.length == ch2.length) { //如果长度相等,再比较

        for (int i = 0; i < ch1.length; i++) {

            if (clearText.indexOf(ch1[i])!= cipherText.indexOf(ch2[i])) {

                 isCorrect = false; //只要有不等的,就为错

                    break;

             } else {//长度不等,直接错误

               isCorrect = false;}}

}

流程图:        

IP扫描模块:IP地址扫描分为单地址和多地址两种,以用户输入的IP地址和线程数为参数采用多线程的方式扫描IP地址;调用PingTester类实现IP地址扫描,PingTester类包含3个部分:构造函数、startPing函数、内部类PingRunner。

关键算法:

try {       //InetAddress 保存了主机名和IP地址

while ((taskIp = getIp()) != null) {    //调用getIp()方法得到IP地址

    InetAddress addr = InetAddress.getByName(taskIp);//获得IP地址

   //isReachable()测试该地址是否可到达。实现会尽最大努力尝试访问主机,

    if (addr.isReachable(5000)) {  //访问超时时间为5s

       System.out.println("IP地址 ["+taskIp+"]是可达的");

            OwnTCPScan.Result.append("IP地址 ["+taskIp+"]是可达的"+"\n");

        } else {    //System.out.println("")在后端显示扫描结果

       System.out.println("IP地址 ["+taskIp+"]不在网络");

            OwnTCPScan.Result.append("IP地址 ["+taskIp+"]不在网络"+"\n");

        }   //OwnTCPScan.Result.append("")在UI界面显示扫描结果

  }

} catch (SocketException e) { //如果访问超时

    System.out.println("IP地址 ["+taskIp+"]没有访问权限");

    OwnTCPScan.Result.append("IP地址 ["+taskIp+"]没有访问权限"+"\n");}

    流程图:

端口扫描模块:根据主机和端口号的扫描采用多线程技术,以用户输入的主机名、线程数与端口范围为参数进行多线程扫描,调用scanPorts函数传递参数,scanPorts函数调用ScanMethod类实现端口的扫描。主要分为3个部分:scanPorts函数、ScanMethod类的构造函数、ScanMethod类的run函数。

关键代码:

try {//Java.net包中有InetAddress类的定义,用于IP地址和域名

InetAddress address = InetAddress.getByName(ip);

        //InetAddress可以根据主机名获取主机的ip地址,也支持输入IP地址

 Socket socket;//定义套接字,调用connect函数查看端口的状态

 SocketAddress socketAddress;//SocketAddress是一个抽象类,传递ip和端口,其实真正实现的不是SocketAddress,而是其子类,这样声明是为了方便调用

 //必须使用SocketAddress的子类来建立SocketAddress对象

 if (ports.length < 1) {

        return;//若数组没有元素,返回,不执行

 }

  //serial是线程号,1号线程检测1,11,21端口,2号线程检测2,12,22端口

 for (port = 0 + serial; port <= ports.length - 1; port += threadNumber) {

socket = new Socket();

socketAddress = new InetSocketAddress(address, ports[port]);

//InetSocketAddress是SocketAddress的实现子类,此类实现 IP 套接字地址(IP 地址 + 端口号),不依赖任何协议

        try {//对目标主机的指定端口进行连接,超时后连接失败

        socket.connect(socketAddress, timeout);

socket.close();  //关闭端口

System.out.println("端口 " + ports[port] + " :开放");

            OwnTCPScan.Result.append("端口 " + ports[port] + " :开放\n");

//在文本区域里更新消息

         } catch (IOException e) {//产生异常表示端口关闭

 System.out.println("端口 " + ports[port] + " :关闭");

            OwnTCPScan.Result.append("端口 " + ports[port] + " :关闭\n");

        }

    }

 } catch (UnknownHostException e) {

    e.printStackTrace();

 }

}

流程图::

猜你喜欢

转载自blog.csdn.net/dw1360585641/article/details/125460253