今天用Java开发主机IP扫描神器,零基础Socket编程详细
Posted Charzous
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了今天用Java开发主机IP扫描神器,零基础Socket编程详细相关的知识,希望对你有一定的参考价值。
目录
一、开发背景
今天我们来开启一个有趣的实战小项目,运用Java网络编程技术开发一个主机IP扫描探测神器,相信你一定感兴趣,用3个词描述就是简单、好玩、有收获!其实,主机IP扫描就是探测一个IP地址范围内有哪些主机是活动的,是网络攻防的基础和前提。
扫描探测一台目标主机包括的具体信息有:目标主机是否活动、主机的操作系统、正在使用哪些端口、对外提供了哪些服务、相关服务的软件版本等,对这些内容的探测可以为网络攻防提供参考信息。对主机的探测工具非常多,比如功能强大的nmap、netcat、superscan,以及国内的x-scanner等。这次我们自己动手来开发一个主机IP扫描探测小程序,来探测目标主机是否活动,更能加深对网络编程的理解和应用。
二、准备工作
三、远程主机 IP 探测
IP地址的探测就是确定被扫描的IP在网络中开闭状态,因此,开发任务的核心点就在于如何判断IP地址活跃状态。这时可以联想到平常我们使用ping命令来判断目标主机是否可达,ping命令是基于ICMP协议通信的。
由上面分析发现,可以使用Java中的InetAddress类中的isReachable方法进行判断,该方法就是基于ICMP协议判断目标是否可达的。描述如下:
A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.
所以,只需要两行代码就能完成这个探测任务:
InetAddress addr = InetAddress.getByName(ip);//IP地址
boolean status=addr.isReachable(timeOut);// timeOut为等待时间(毫秒)
若status的值为真,则表示该主机是活跃的,否则可能不存在或离线。
分析到这里,为了实现一个IP范围的扫描,比如对192.168.11.1到192.168.11.100之间的IP地址进行探测,如何将IP地址正确地输入呢?
我们都知道,IPv4的地址格式是由一个32位二进制数来表示的,为了简单记录,把它分为4个字节,每个字节表示8位,进而使用一个十进制数值来表示。
比如192.168.11.1实际就是由4字节32位表示:11000000. 10101000. 00001011. 00000001,而192.168.11.100表示为:11000000. 10101000. 00001011. 01100100
观察之后发现,实际就是二进位的变化导致数值的编号的变化,要实现递增的IP地址,可以更为简单的将32位直接表示为一个有符号的十进制数值,前者就是-1062728959,后者是-1062728860。
分析到规律之后,接下来实现这个算法。
四、核心算法
很明显,我们需要两个算法:IP地址转为十进制数和十进制数转为IP地址。
首先,确定一个IP地址范围就需要将起始IP以及结束IP地址转化为十进制数值表示,两端边界就是IP地址的区间,然后在这个区间不断递增,将每个数值转为IP地址进而才能输入判断是否可达。
1、IP地址转化为十进制数
这个算法只涉及按位或运算,相对简单。
public static int ipToLong(String ip) {
String[] ipArray = ip.split("\\\\.");
int num = 0;
for (int i = 0; i < ipArray.length; i++) {
int valueOfSection = Integer.parseInt(ipArray[i]);//将8位字符串转化为整型
//对每段ip值左移,再进行按位或运算,最后得到一个十进制数值
num = (valueOfSection << 8 * (3 - i)) | num;
}
return num;
}
2、十进制数转化为IP地址
这个过程是上面算法的逆过程,主要涉及按位与和无符号右移。
public static String longToIp(int num) {
String[] ipString = new String[4];
for (int i = 0; i < 4; i++) {
//将数值每8位跟 11111111 按位与运算,得到8位的二进制数
int and = num & (255 << (8 * (3 - i)));
//再将每段进行无符号右移,得到每段的ip值
ipString[i] = String.valueOf(and >>> (8 * (3 - i)));
}
String ip = String.join(".", ipString);//将字符串数组拼接为IP地址形式
return ip;
}
五、主机 IP 扫描神器界面
核心部分已经分析并且完成算法实现,现在来组装IP扫描神器的界面了,这个就很简单啦!
先来看看界面,如图。看到这里,是否跟你想象的一样呢?
可以看到这里除了主机IP扫描的功能,还有一个类似CMD执行命令的功能,后面会简单介绍。
界面代码:
/**
* HostScannerFX.java
* @author Charzous
* @date 2021-05-30 下午 07:03
* Copyright (c) 2020-10-30
* All right reserved.
*
*/
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
public class HostScannerFX extends Application {
private TextArea result = new TextArea();
private TextField begin = new TextField();
private TextField end = new TextField();
private TextField tfCmd = new TextField();
private Button PCScan = new Button("主机扫描");
private Button stop=new Button("停止");
private Button exeCmd = new Button("执行命令");
private Thread readThread;
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane mainPane = new BorderPane();
VBox vBox = new VBox();
vBox.setSpacing(10);
vBox.setPadding(new Insets(10, 20, 10, 20));
VBox.setVgrow(result, Priority.ALWAYS);
vBox.getChildren().addAll(new Label("扫描结果:"), result);
mainPane.setCenter(vBox);
HBox hBox1 = new HBox();
hBox1.setSpacing(10);
hBox1.setPadding(new Insets(10, 20, 10, 20));
hBox1.setAlignment(Pos.CENTER);
begin.setPrefWidth(180);
end.setPrefWidth(180);
hBox1.getChildren().addAll(new Label("起始地址:"), begin, new Label("结束地址:"), end, PCScan,stop);
HBox hBox2 = new HBox();
hBox2.setSpacing(10);
hBox2.setPadding(new Insets(10, 20, 10, 20));
hBox2.setAlignment(Pos.CENTER);
HBox.setHgrow(tfCmd, Priority.ALWAYS);
hBox2.getChildren().addAll(new Label("输入命令格式:"), tfCmd, exeCmd);
VBox vBox1 = new VBox();
vBox1.setSpacing(10);
vBox1.setPadding(new Insets(10, 20, 10, 20));
vBox1.setAlignment(Pos.CENTER);
vBox1.getChildren().addAll(hBox1, hBox2);
mainPane.setBottom(vBox1);
Scene scene = new Scene(mainPane, 800, 500);
primaryStage.setScene(scene);
primaryStage.setTitle("MyHostScanner");
primaryStage.show();
//关闭窗口
primaryStage.setOnCloseRequest(event -> {
System.exit(0);
});
}
}
现在这个还是不能用的,我们需要对界面的按钮绑定事件,也就是将上面的IP探测扫描功能加进来,具体看下面。
六、各功能代码及IP扫描演示
1、主机扫描按钮
上面分析过,扫描探测就是通过ICMP建立通信,这需要耗时,因此将扫描任务放到一个线程中执行,不影响主程序操作。
PCScan.setOnAction(event -> {
String host = begin.getText().trim();
String endHost = end.getText().trim();
if (host.equals("")||endHost.equals("")){
result.appendText("请正确输入起始地址和结束地址!\\n");
return;
}
int beginIp = ipToLong(host);
int endIp = ipToLong(endHost);
readThread = new Thread(() -> {
for (int i = beginIp; i <= endIp; i++) {
//判断线程状态标志,如果被终止则停止线程
if (readThread.isInterrupted()){
readThread.interrupt();
result.appendText("终止扫描!");
break;
}
String ip = longToIp(i);
try {
InetAddress address = InetAddress.getByName(ip);
boolean status = address.isReachable(200);
Platform.runLater(() -> {
if (status == true)
result.appendText(address + " is reachable.\\n");
else
result.appendText(address + " is not reachable.\\n");
});
} catch (IOException e) {
e.printStackTrace();
}
}
result.appendText("扫描结束!\\n");
});
readThread.start();
});
2、停止按钮
停止的意思就是我们不然程序继续扫描了,终止线程操作,很简单的实现。
stop.setOnAction(event -> {
readThread.interrupt();
});
这个是结合上面扫描线程中,判断线程状态共同实现的。
//判断线程状态标志,如果被终止则停止线程
if (readThread.isInterrupted()){
readThread.interrupt();
result.appendText("终止扫描!");
break;
}
3、执行命令按钮
执行命令是增加的一个功能,主要使用Java里面的Process类和Runtime类共同实现的,类似在命令提示符cmd中输入命令执行功能。
exeCmd.setOnAction(event -> {
String cmd=tfCmd.getText();
if (cmd.equals("")){
result.appendText("请正确输入执行命令!\\n");
return;
}
readThread = new Thread(()->{
try {
Process process = Runtime.getRuntime().exec(cmd);
InputStream in = process.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(in,"gbk"));
String msg=null;
while ((msg=br.readLine())!=null){
String msgTemp=msg;
Platform.runLater(()->{
result.appendText(msgTemp+"\\n");
});
}
}
catch (IOException e) {
System.err.println(e.getMessage());
}
});
readThread.start();
});
现在看看效果了。我所在的局域网的网络是10.173.40.0,我的IP地址是10.173.40.25,所以进行了一个小范围的探测扫描,发现几个IP地址也是活动状态。
然后,查看一下百度的IP地址,扫描看看。
发现百度所在的网段许多IP地址是活动的。
最后
今天来用Java开发主机IP扫描神器,零基础Socket编程详细教程,这篇内容是不是简单、有趣、有收获呢?欢迎交流学习!
学习Java开发,Socket网络编程等知识,里面有许多有趣的小程序可以做,最近我也在跟着这一套 《Java 工程师学习成长知识图谱》进行体系的学习,是CSDN官方推出的,质量很不错!其中包含了Java专业体系结构完整详细,推荐给大家学习使用,有兴趣可以扫码查看,最近我也在学习当中,当然,我的文章会记录学习,欢迎大家阅读,比如我的专栏《Socket网络编程》、《Java宝藏》。
展开就是这样的,尺寸870mm*560mm排版好看,内容很充实。推荐给有需要的伙伴,一起来学习Java开发!
如果觉得不错欢迎“一键三连”哦,点赞收藏关注,评论提问建议,欢迎交流学习!一起加油进步!
本篇内容首发我的CSDN博客:https://csdn-czh.blog.csdn.net/article/details/117403031
以上是关于今天用Java开发主机IP扫描神器,零基础Socket编程详细的主要内容,如果未能解决你的问题,请参考以下文章