Java从入门到精通之网络编程实现的简单端口扫描器示例
龚超 2018-06-19 来源 : 阅读 1345 评论 0

摘要:本文实例讲述了Java网络编程实现的简单端口扫描器。分享给大家供大家参考,具体如下,希望对大家学习Java从入门到精通有所帮助。

本文实例讲述了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或域名
ListportList = new LinkedList();// 定义一个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, ListportSet,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 ListportList; // 待扫描的端口的List集合
private int threadNumber, serial, timeout; // 线程数,这是第几个线程,超时时间
public ScanMethod(String ip, ListportList, 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缓存操作技巧汇总》

希望这篇文章可以帮助到你,总之同学们,IT资讯尽在职坐标。

本文由 @职坐标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论
本文作者 联系TA

擅长针对企业软件开发的产品设计及开发的细节与流程设计课程内容。座右铭:大道至简!

  • 370
    文章
  • 22915
    人气
  • 87%
    受欢迎度

已有23人表明态度,87%喜欢该老师!

进入TA的空间
求职秘籍 直通车
  • 索取资料 索取资料 索取资料
  • 答疑解惑 答疑解惑 答疑解惑
  • 技术交流 技术交流 技术交流
  • 职业测评 职业测评 职业测评
  • 面试技巧 面试技巧 面试技巧
  • 高薪秘笈 高薪秘笈 高薪秘笈
TA的其他文章 更多>>
WEB前端必须会的基本知识题目
经验技巧 93% 的用户喜欢
Java语言中四种遍历List的方法总结(推荐)
经验技巧 91% 的用户喜欢
Java语言之SHA-256加密的两种实现方法详解
经验技巧 75% 的用户喜欢
java语言实现把两个有序数组合并到一个数组的实例
经验技巧 75% 的用户喜欢
通过Java语言代码来创建view的方法
经验技巧 80% 的用户喜欢
其他海同师资 更多>>
吕益平
吕益平 联系TA
熟悉企业软件开发的产品设计及开发
孔庆琦
孔庆琦 联系TA
对MVC模式和三层架构有深入的研究
周鸣君
周鸣君 联系TA
擅长Hadoop/Spark大数据技术
范佺菁
范佺菁 联系TA
擅长Java语言,只有合理的安排和管理时间你才能做得更多,行得更远!
金延鑫
金延鑫 联系TA
擅长与学生或家长及时有效沟通
经验技巧30天热搜词 更多>>

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程