为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

Java网络编程-Socket实现的扫描程序设计

2023-06-20 5页 doc 153KB 3阅读

用户头像 个人认证

is_859878

暂无简介

举报
Java网络编程-Socket实现的扫描程序设计  Java网络编程Socket实现的扫描程序设计  扫描程序设计目标主机扫描是网络功防的基础和前提,扫描探测一台目标主机包括:确定该目标主机是否活动、目标主机的操作系统、正在使用哪些端口、对外提供了哪些服务、相关服务的软件版本等等,对这些内容的探测就是为了“对症下药”,为攻防提供参考信息。对主机的探测工具非常多,比如大名鼎鼎的nmap、netcat、superscan,以及国内的x-scanner等等。我们自己动手做简单扫描软件或工具,用于加深对网络编程的理解。知识点:进一步理解newSocket()、Process类和IC...
Java网络编程-Socket实现的扫描程序设计
  Java网络编程Socket实现的扫描程序设计  扫描程序设计目标主机扫描是网络功防的基础和前提,扫描探测一台目标主机包括:确定该目标主机是否活动、目标主机的操作系统、正在使用哪些端口、对外提供了哪些服务、相关服务的软件版本等等,对这些内容的探测就是为了“对症下药”,为攻防提供参考信息。对主机的探测工具非常多,比如大名鼎鼎的nmap、netcat、superscan,以及国内的x-scanner等等。我们自己动手做简单扫描软件或工具,用于加深对网络编程的理解。知识点:进一步理解newSocket()、Process类和ICMP。一、程序设计第一步:主机扫描(远程主机探测)(1)通过指定的IP地址范围,发现该范围中活跃的主机,例如指定192.168.0.15-192.168.1.100范围。新建Java包,命名chapter09,创建主机扫描程序HostScannerFX.java,窗口界面如图9.1所示,并在“主机扫描”按钮中设置主机探测关键代码,例如类似代码:InetAddressaddr=InetAddress.getByName(host);//host为IP地址booleanstatus=addr.isReachable(timeOut);//timeOut为等待时间(毫秒)若status的值为真,则表示该主机是活跃的,否则可能不存在或离线。图9.1主机扫描窗体在主机扫描的过程中就要涉及到指定ip地址范围的循环遍历,大家思考如何实现。最容易想到的思路可能就是将起始范围的两个ip地址分别拆分成字符串数组,再进行相关的匹配、多重循环等操作。这个过程实际是繁琐低效的。更好的一种思路就是将ip地址转换为整数形式,一个网段就是0-255之间,刚好就是1个字节的范围,四个网段表示就需要四个字节,刚好是一个int整数的范围。在两个整数之间循环遍历,循环体中将每一个整数转换回ip地址进行处理即可。所以关键就在于实现ip与整数之间的互相转换,基本原理阐述如下:假设ip地址为192.168.234.3:每个网段都用二进制表示:192(10)=11000000(2);168(10)=10101000(2);234(10)=11101010(2);3(10)=00000011(2)。所以连在一起就是:11000000101010001110101000000011,对应的int数字就是-1062671869。具体算法:192左移24位:11000000000000000000000000000000168左移16位:00000000101010000000000000000000234左移08位:00000000000000001110101000000000003左移00位:00000000000000000000000000000011将之拼装即按位或结果:11000000101010001110101000000011即-1062671869将int类型的数字转换成ip地址,其实就是上述过程的逆过程(在具体运算中要用到和0xff与的操作)。这些操作需要用到java的位运算操作,例如左移<<、右移>>、位与&、位或|。这里给出ip转int的方法ipToInt,大家自行实现对应的int转ip的方法intToIp:/***字符串格式ip转整数**/publicstaticintipToInt(Stringip){String[]ipArray=ip.split(".");intnum=0;for(inti=0;i{taDisplay.appendText(msgTemp+"\n");});}}catch(IOExceptione){System.err.println(e.getMessage());}同样,很多命令行程序执行时间较长,例如netstat命令,所以“命令执行”按钮中的代码也需要放在新线程中执行。二、程序设计第二步:端口扫描扫描目的主机开放的端口是常见操作:攻(寻找目的主机开放的端口)与防(检测本机异常开放的端口)。基本的端口扫描可使用的技术:​i.NewSocket(host,port);​ii.TCPConnect端口扫描;创建端口扫描程序PortScannerFX.java,主界面如图9.2所示。图9.2端口扫描程序主界面(1)在“扫描”按钮的点击事件响应中添加如下类似代码:......try{Socketsocket=newSocket(host,port);socket.close();Stringmsg="端口"+port+"isopen\n";//显示区显示相应信息......}catch(IOExceptione){Stringmsg="端口"+port+"isclosed\n";......}用trycatch进行捕获,如果能打开,就不会抛出异常,否则利用IOException判定该主机的port端口并没有开放,该方法对于未开放的端口,默认等待时间秒数量级。(2)上述方法在遇到端口关闭时等待时间过长,时间成本过高。在“快速扫描”按钮的事件响应程序中添加如下类似代码:......try{//空套接字,不尝试连接工作Socketsocket=newSocket();socket.connect(newInetSocketAddress(host,port),200);socket.close();Stringmsg="端口"+port+"isopen\n";......}catch(IOExceptione){......}在这里设定连接等待时间,毫秒时间单位,如设定为200ms。根据设定的时间尝试连接对方。(3)多线程扫描:即便使用快速扫描的方式,如果扫描整个端口范围,还是耗时较久。可以结合快速扫描,开启多线程加快速度,每一个线程负责扫描一段范围,分而治之加快速度。在多线程扫描中,出来的结果不是按顺序排列,我们可以考虑没必要把关闭的端口显示出来,只需要显示开放的端口,毕竟我们只关心哪些端口开放了,这时就需要有一个变量来统计已经扫描了多少端口,这样可以通知用户端口扫描结束。这个变量需要考虑并发访问的问题,除了可以使用synchronize方式,还可以使用效率更高的原子操作数据类型,保证线程安全,例如可以定义一个静态的整型原子数据类型变量:staticAtomicIntegerportCount=newAtomicInteger(0);//portCount用于统计已扫描的端口数量该数据类型提供set(intvalue)、get()、incrementAndGet()等方法,可以满足我们的要求。记住每次重新扫描的时候要把该变量值重置为0。下面是实现了Runnable接口的内部类ScanHandler,部分参考代码如下:classScanHandlerimplementsRunnable{privateinttotalThreadNum;//用于端口扫描的总共线程数,默认为10privateintthreadNo;//线程号,表示第几个线程publicScanHandler(intthreadNo){this.totalThreadNum=10;this.threadNo=threadNo;}publicScanHandler(intthreadNo,inttotalThreadNum){this.totalThreadNum=totalThreadNum;this.threadNo=threadNo;}@Overridepublicvoidrun(){//startPort和endPort为成员变量,表示需要扫描的起止端口for(intport=startPort+threadNo;port<=endPort;port=port+totalThreadNum){try{Socketsocket=newSocket();socket.connect(newInetSocketAddress(host,port),200);socket.close();Stringmsg="端口"+port+"isopen\n";Platform.runLater(()->{taDisplay.appendText(msg);});}catch(IOExceptione){Stringmsg="端口"+port+"isclosed\n";*Platform.runLater(()->{**taDisplay.appendText(msg);});}portCount.incrementAndGet();//扫描的端口数+1}if(portCount.get()==(endPort-startPort+1)){portCount.incrementAndGet();//加1,使得不再输出下面的线程扫描结束的信息Platform.runLater(()->{taDisplay.appendText("\n----------------多线程扫描结束--------------------\n");});}}}根据上面的内部类的实现,在“多线程扫描”按钮中,通过合适的循环语句,生成多个线程并行扫描,请自行完成。四、扩展练习:完善主机扫描和端口扫描程序(1)使用线程技术,使得按钮执行不会卡死主界面,但如果用户再次点击按钮执行新任务,前面的没有完成的线程任务输出就会和后面任务的输出内容混杂显示在一起,请改进这两个程序,使得每次点击按钮时,先关闭之前执行的扫描线程。注意,不要使用Thread.stop()方法,该方法不安全,已经被废弃。大家搜索有关ThreadGroup类、interrupt()、isInterrupted()等用法,实现以上需求;(2)两个程序各自增加一个“停止”按钮,使得扫描或长时间执行的命令可以停止(实质也是需要关闭对应线程,能完成上面的任务,这个任务也就很容易实现)。(3)扫描时关闭的端口其实没必要显示,这不是我们关心的结果。但不显示的话,不知道扫描的进度情况,请增加一个进度条(ProgressBar类)功能,动态显示扫描的进度。ProgressBar可以通过setProgress(doublevalue)来设置进度条的动态变化,value用0到1之间范围表示进度的百分比,getProgress()返回double类型的进度值。效果类似图9.3。图9.3带进度条的扫描窗口(4)主机扫描也可以类似端口扫描,使用多线程方式尝试实现,并同样实现进度条功能(将IP地址用整数的方式表示,就可以类似端口扫描方式:多线程分段扫描。但如果使用ip转int方式,在A网段的127到128之间会出现正负数的跳变,建议将ipToInt方法重构为ipToLong方法)。完整代码HostScannerFXpackagechapter09;importjavafx.application.Application;importjavafx.application.Platform;importjavafx.geometry.Insets;importjavafx.geometry.Pos;importjavafx.scene.Parent;importjavafx.scene.Scene;importjavafx.scene.control.Button;importjavafx.scene.control.Label;importjavafx.scene.control.TextArea;importjavafx.scene.control.TextField;importjavafx.scene.layout.BorderPane;importjavafx.scene.layout.HBox;importjavafx.scene.layout.Priority;importjavafx.scene.layout.VBox;importjavafx.stage.Stage;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.net.InetAddress;importjava.util.Scanner;importjava.util.concurrent.atomic.AtomicInteger;/***Author:*Data:2020/11/1*description:*/publicclassHostScannerFXextendsApplication{privateTextFieldtfcommand=newTextField();privateTextFieldtfstart=newTextField();privateTextFieldtfend=newTextField();privateTextAreataResult=newTextArea();privateButtonbtnScan=newButton("主机扫描");privateButtonbtnExcu=newButton("执行命令");privateButtonbtnshut=newButton("停止扫描");Threadthread1;privatelongstartIp;privatelongendIp;privateThreadGroupthreadGroup=newThreadGroup("scanThread");staticAtomicIntegerhostCount=newAtomicInteger(0);@Overridepublicvoidstart(StageprimaryStage)throwsException{BorderPanemainpane=newBorderPane();HBoxtophbox=newHBox();tophbox.setSpacing(10);tophbox.setPadding(newInsets(10,20,10,20));tophbox.setAlignment(Pos.CENTER);tophbox.getChildren().addAll(newLabel("起始地址"),tfstart,newLabel("结束地址"),tfend,btnScan,btnshut);HBoxtophbox1=newHBox();tophbox1.setSpacing(10);tophbox1.setPadding(newInsets(10,20,10,20));tophbox1.setAlignment(Pos.CENTER);tophbox1.getChildren().addAll(newLabel("输入命令格式"),tfcommand,btnExcu);VBoxvBox=newVBox();vBox.setPadding(newInsets(10,20,10,20));vBox.setSpacing(10);vBox.getChildren().addAll(newLabel("扫描结果"),taResult);//设置文本框宽度VBox.setVgrow(taResult,Priority.ALWAYS);VBoxvBox1=newVBox();vBox1.setPadding(newInsets(10,20,10,20));vBox1.setSpacing(10);vBox1.getChildren().addAll(tophbox,tophbox1);tfcommand.setPrefWidth(500);mainpane.setCenter(vBox);mainpane.setBottom(vBox1);Parentroot;Scenescene=newScene(mainpane,800,500);primaryStage.setScene(scene);primaryStage.show();btnScan.setOnAction(event->{this.startIp=IpUtils.ipToLong(tfstart.getText());this.endIp=IpUtils.ipToLong(tfend.getText());intthread=16;hostCount.set(0);for(inti=0;i{thread1=newThread(()->{try{Stringcmd=tfcommand.getText();Processprocess=Runtime.getRuntime().exec(cmd);InputStreamin=process.getInputStream();BufferedReaderbr=newBufferedReader(newInputStreamReader(in,"GBK"));Stringmsg;while((msg=br.readLine())!=null){Stringmsgtemp=msg;Platform.runLater(()->{taResult.appendText(msgtemp+"\n");});}}catch(IOExceptione){e.printStackTrace();}});thread1.start();});}classScanHandlerimplementsRunnable{privateinttotalThreadNum;privateintthreadNo;publicScanHandler(intthreadNo){this.totalThreadNum=10;this.threadNo=threadNo;}publicScanHandler(intthreadNo,inttotalThreadNum){this.totalThreadNum=totalThreadNum;this.threadNo=threadNo;}@Overridepublicvoidrun(){for(longhost=startIp+threadNo;host<=endIp;host=host+totalThreadNum){if(Thread.currentThread().isInterrupted()){System.out.println("interrupted!");break;}try{booleanres=isReachable(IpUtils.longToIp(host));if(res){longfinalHost1=host;Platform.runLater(()->{taResult.appendText(IpUtils.longToIp(finalHost1)+"isreachable.\n");});}}catch(IOExceptione){e.printStackTrace();}hostCount.incrementAndGet();}if(hostCount.get()==(endIp-startIp+1)){hostCount.incrementAndGet();Platform.runLater(()->{taResult.appendText("扫描完毕");});}}}privatebooleanisReachable(Stringhost)throwsIOException{InetAddressaddress=InetAddress.getByName(host);returnaddress.isReachable(100);}//publicstaticvoidmain(String[]args){//System.out.println(StringIPAddOne("192.168.1.255"));//System.out.println(ipToInt("192.168.1.255"));//System.out.println(longToIp(-1062731264));//}}IpUtilspackagechapter09;/***description:*author:*date:2020/11/1*/publicclassIpUtils{publicstaticintipToInt(Stringip){String[]ipArray=ip.split("\\.");intnum=0;for(inti=0;i>>24)));sb.append(".");//将高8位置0,然后右移16位sb.append(String.valueOf((ip&0x00FFFFFF)>>>16));sb.append(".");//将高16位置0,然后右移8位sb.append(String.valueOf((ip&0x0000FFFF)>>>8));sb.append(".");//将高24位置0sb.append(String.valueOf((ip&0x000000FF)));returnsb.toString();}publicstaticlongipToLong(StringstrIp){String[]s=strIp.split("\\.");longip=(Long.parseLong(s[0])<<24)+(Long.parseLong(s[1])<<16)+(Long.parseLong(s[2])<<8)+(Long.parseLong(s[3]));returnip;}publicstaticStringlongToIp(longlongIp){//采用SB方便追加分隔符"."StringBuffersb=newStringBuffer("");sb.append(String.valueOf(longIp>>24)).append(".").append(String.valueOf((longIp&0x00ffffff)>>16)).append(".").append(String.valueOf((longIp&0x0000ffff)>>8)).append(".").append(String.valueOf(longIp&0x000000ff));returnsb.toString();}//测试publicstaticvoidmain(String[]args){intintIP;System.out.println(intIP=ipToInt("192.168.0.1"));System.out.println(ipToInt("192.168.0.254"));System.out.println(intToIp(intIP));//System.out.println(ipToInt("122.1.0.127"));//System.out.println(ipToInt("122.1.0.128"));System.out.println(ipToLong("192.168.0.127"));System.out.println(ipToLong("192.168.0.128"));}}PortScannerFXpackagechapter09;importchapter05.TCPThreadServer;importjavafx.application.Application;importjavafx.application.Platform;importjavafx.geometry.Insets;importjavafx.geometry.Pos;importjavafx.scene.Parent;importjavafx.scene.Scene;importjavafx.scene.control.*;importjavafx.scene.layout.BorderPane;importjavafx.scene.layout.HBox;importjavafx.scene.layout.Priority;importjavafx.scene.layout.VBox;importjavafx.stage.Stage;importorg.omg.PortableInterceptor.HOLDING;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.net.InetAddress;importjava.net.InetSocketAddress;importjava.net.Socket;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.atomic.AtomicInteger;/***Author:*Data:2020/11/1*description:*/publicclassPortScannerFXextendsApplication{privateTextFieldtfip=newTextField("192.168.0.1");privateTextFieldtfstart=newTextField("1");privateTextFieldtfend=newTextField("200");privateTextAreataResult=newTextArea();privateButtonbtnScan=newButton("扫描");privateButtonbtnStop=newButton("停止扫描");privateButtonbtnScanFast=newButton("快速扫描");privateButtonbtnScanThread=newButton("多线程扫描");privateButtonbtnexit=newButton("退出");privateintportstart;privateintportend;privateStringhost;privateExecutorServiceexecutorService=Executors.newCachedThreadPool();Threadthread;Threadthread1;staticAtomicIntegerportCount=newAtomicInteger(0);privateThreadGroupthreadGroup=newThreadGroup("scanThread");privateProgressBarprogressBar=newProgressBar(0);privateLabelprogressLabel=newLabel("0%");@Overridepublicvoidstart(StageprimaryStage)throwsException{BorderPanemainpane=newBorderPane();HBoxtophbox=newHBox();tophbox.setSpacing(10);tophbox.setPadding(newInsets(10,20,10,20));tophbox.setAlignment(Pos.CENTER);tophbox.getChildren().addAll(newLabel("目标主机ip:"),tfip,newLabel("起始端口号"),tfstart,newLabel("结束端口号"),tfend);HBoxtophbox1=newHBox();tophbox1.setSpacing(10);tophbox1.setPadding(newInsets(10,20,10,20));tophbox1.setAlignment(Pos.CENTER);tophbox1.getChildren().addAll(btnScan,btnScanFast,btnScanThread,btnStop,btnexit);HBoxprogressbox=newHBox();progressbox.setAlignment(Pos.CENTER);progressbox.setSpacing(10);progressbox.getChildren().addAll(progressLabel,progressBar);progressBar.setPrefWidth(600);VBoxvBox=newVBox();vBox.setPadding(newInsets(10,20,10,20));vBox.setSpacing(10);vBox.getChildren().addAll(newLabel("端口扫描结果"),taResult);//设置文本框宽度VBox.setVgrow(taResult,Priority.ALWAYS);VBoxvBox1=newVBox();vBox1.setPadding(newInsets(10,20,10,20));vBox1.setSpacing(10);vBox1.getChildren().addAll(tophbox,progressbox,tophbox1);tfip.setPrefWidth(150);mainpane.setCenter(vBox);mainpane.setBottom(vBox1);Scenescene=newScene(mainpane,800,500);primaryStage.setScene(scene);primaryStage.show();btnScan.setOnAction(event->{progressBar.setProgress(0);progressLabel.setText("0%");Stringhost=tfip.getText();thread=newThread(()->{intportstart=Integer.parseInt(tfstart.getText());intportend=Integer.parseInt(tfend.getText());inttotalport=portend-portstart+1;intstartp=portstart;while(portstart<=portend){System.out.println("scaningport"+portstart);try{Socketsocket=newSocket(host,portstart);socket.close();Stringmsg="端口"+portstart+"isOpen!\r\n";taResult.appendText(msg);}catch(IOExceptione){//e.printStackTrace();Stringmsg="端口"+portstart+"isClosed!\r\n";taResult.appendText(msg);}doubleprogress=(double)(portstart-startp)/totalport;Platform.runLater(()->{progressBar.setProgress(progress);progressLabel.setText((int)(progress*100)+"%");});portstart++;}});thread.start();});btnScanFast.setOnAction(event->{progressBar.setProgress(0);progressLabel.setText("0%");host=tfip.getText();thread1=newThread(()->{portstart=Integer.parseInt(tfstart.getText());portend=Integer.parseInt(tfend.getText());inttotalport=portend-portstart+1;intstartp=portstart;while(portstart<=portend){try{Socketsocket=newSocket();socket.connect(newInetSocketAddress(host,portstart),200);socket.close();Stringmsg="端口"+portstart+"isOpen!\r\n";taResult.appendText(msg);}catch(IOExceptione){//e.printStackTrace();Stringmsg="端口"+portstart+"isClosed!\r\n";taResult.appendText(msg);}doubleprogress=(double)(portstart-startp)/totalport;Platform.runLater(()->{progressBar.setProgress(progress);progressLabel.setText((int)(progress*100)+"%");});portstart++;}});thread1.start();});btnScanThread.setOnAction(event->{host=tfip.getText();this.portstart=Integer.parseInt(tfstart.getText());this.portend=Integer.parseInt(tfend.getText());intthread=4;portCount.set(0);for(inti=0;i{btnStop.setDisable(true);btnScan.setDisable(false);btnScanFast.setDisable(false);btnScanThread.setDisable(false);try{threadGroup.list();threadGroup.interrupt();}catch(Exceptione){}});btnexit.setOnAction(event->{try{threadGroup.interrupt();}catch(Exceptione){}System.exit(0);});}publicstaticintipToInt(Stringip){String[]ipArray=ip.split("\\.");intnum=0;for(inti=0;i>8;}returnresult.toString();}classScanHandlerimplementsRunnable{privateinttotalThreadNum;privateintthreadNo;publicScanHandler(intthreadNo){this.totalThreadNum=10;this.threadNo=threadNo;}publicScanHandler(inttotalThreadNum,intthreadNo){this.totalThreadNum=totalThreadNum;this.threadNo=threadNo;}@Overridepublicvoidrun(){for(intport=portstart+threadNo;port<=portend;port=port+totalThreadNum){doubleprogress=(double)portCount.get()/(portend-portstart+1);Platform.runLater(()->{progressBar.setProgress(progress);progressLabel.setText((int)(progress*100)+"%");});try{Socketsocket=newSocket();socket.connect(newInetSocketAddress(host,port),200);socket.close();Stringmsg="端口"+port+"isopen\n";Platform.runLater(()->{taResult.appendText(msg);});}catch(IOExceptione){Stringmsg="端口"+port+"isclosed\n";Platform.runLater(()->{taResult.appendText(msg);});e.printStackTrace();}portCount.incrementAndGet();}if(portCount.get()==(portend-portstart+1)){portCount.incrementAndGet();Platform.runLater(()->{taResult.appendText("-----多线程扫描结束-------");});}}}//publicstaticvoidmain(String[]args){//System.out.println(StringIPAddOne("192.168.1.255"));//System.out.println(ipToInt("192.168.1.255"));//System.out.println(longToIp(-1062731264));//}}Stringmsg="端口"+port+"isclosed\n";Platform.runLater(()->{taResult.appendText(msg);});e.printStackTrace();}portCount.incrementAndGet();}if(portCount.get()==(portend-portstart+1)){portCount.incrementAndGet();Platform.runLater(()->{taResult.appendText("-----多线程扫描结束-------");});}}}//publicstaticvoidmain(String[]args){//System.out.println(StringIPAddOne("192.168.1.255"));//System.out.println(ipToInt("192.168.1.255"));//System.out.println(longToIp(-1062731264));//}} -全文完-
/
本文档为【Java网络编程-Socket实现的扫描程序设计】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索