多线程端⼝扫描器的实现(java)
这是我⼤三下学期课程设计的题⽬,没有想象中的那么难。
⼀、要求:
1.利⽤Socket通信机制实现⼀个多线程的端⼝扫描器。
2.设计要求:
2.1⽤户界⾯:⽤户可以输⼊IP地址或IP地址段;输⼊端⼝号或端⼝号范围;列表显⽰主机名、开放的端⼝及开放端⼝上相应的服务或恶意程序的名称;功能按钮。
2.2使⽤多线程机制对某⼀地址(段)的主机端⼝进⾏扫描;说明开放端⼝的类型(如UDP端⼝还是TCP端⼝);查询数据库,对开放的端⼝进⾏说明(如提供的服务或存在的风险)。
2.3有关端⼝与服务或恶意程序的映射关系保存为数据库表,以扫描出的开放端⼝号为关键字查询表,将端⼝的说明显⽰在界⾯的列表框中。
⼆、代码
功能实现类:
public class PortScanner{
public static void main(String[] args){
new EditorWin();
}
}
class EditorWin extends JFrame implements  ActionListener {
private JLabel startIp,endIp,l_startPort,l_endPort,l_portOfThread ,showResult ,empty,type ,status;
private JTextField f_startIp,f_endIp,f_startPort,f_endPort,f_portOfThread ;
private JScrollPane result ;
private JComboBox comboBox ;
private JButton startScanner,exitScanner ,clear,reset;
private JPanel top,bottom ;
private JTextArea message ;
private String startIpStr ,endIpStr;
private int startPort,endPort,portOfThread ,threadNum ;
public EditorWin(){
this.setTitle("多线程端⼝扫描器") ;
startIp = new JLabel("扫描的Ip") ;
l_startPort = new JLabel("起始端⼝") ;
l_endPort = new JLabel("结束端⼝") ;
l_portOfThread = new JLabel("每个线程扫描端⼝数") ;
status=new JLabel("未开始扫描") ;
showResult = new JLabel("扫描结果") ;
endIp = new JLabel("结束Ip");
empty = new JLabel("                                                            ") ;
type = new JLabel("选择扫描的类型") ;
startScanner = new JButton("扫描");
exitScanner = new  JButton("退出");
clear = new JButton("清空") ;
reset = new JButton("重置") ;
f_endIp = new JTextField(12) ;
f_startIp = new JTextField(12) ;
f_startPort = new JTextField(5) ;
f_endPort = new JTextField(5) ;
f_portOfThread = new JTextField(5) ;
message = new JTextArea(20,20) ;
result = new JScrollPane(message) ;
result.setColumnHeaderView(showResult) ;
result.setColumnHeaderView(showResult) ;
comboBox = new JComboBox() ;
comboBox.addItem("地址");
comboBox.addItem("地址段");
endIp.setVisible(false) ;
f_endIp.setVisible(false) ;
top = new JPanel() ;
top.add(type);
top.add(comboBox) ;
top.add(startIp) ;
top.add(f_startIp) ;
top.add(endIp) ;
top.add(f_endIp) ;
top.add(l_startPort) ;
top.add(f_startPort) ;
top.add(l_endPort) ;
top.add(f_endPort) ;
top.add(l_portOfThread) ;
top.add(f_portOfThread) ;
bottom = new JPanel() ;
bottom.add(status) ;
bottom.add(empty) ;
bottom.add(empty) ;
bottom.add(empty) ;
bottom.add(empty) ;
bottom.add(empty) ;
bottom.add(empty) ;
bottom.add(startScanner) ;
bottom.add(clear);
bottom.add(reset);
bottom.add(exitScanner) ;
this.add(top,BorderLayout.NORTH);
this.add(result,BorderLayout.CENTER) ;
this.add(bottom,BorderLayout.SOUTH) ;
comboBox.addActionListener(this) ;
startScanner.addActionListener(this) ;
exitScanner.addActionListener(this) ;
clear.addActionListener(this) ;
reset.addActionListener(this) ;
setSize(1000, 500);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@Override
public void actionPerformed(ActionEvent e) {
Source()==startScanner){ //点击扫描按钮
//点击时刻
startIpStr = Text().trim() ;  //得到输⼊的Ip
if(checkIP(startIpStr)){
/
/判断是否为数字
try{
startPort = Integer.parseInt(Text().trim()) ;
endPort =  Integer.parseInt(Text().trim()) ;
portOfThread  =Integer.parseInt(Text().trim())  ;
threadNum = (endPort-startPort)/portOfThread+1 ;
//普安段端⼝号的范围
if(startPort<0||endPort>65535||startPort>endPort){
JOptionPane.showMessageDialog(this, "端⼝号范围:0~65535,并且最⼤端⼝号应⼤于最⼩端⼝号!") ;      }
else{
if(portOfThread>endPort-startPort||portOfThread<1){
JOptionPane.showMessageDialog(this, "每个线程扫描的端⼝数不能⼤于所有的端⼝数且不能⼩于1") ;      }else{
if(((String) SelectedItem()).equals("地址")){
if(((String) SelectedItem()).equals("地址")){
message.append("************************************************************"+"\n") ;
message.append("正在扫描  "+startIpStr+"          每个线程扫描端⼝个数"+portOfThread+"\n"+"开启的线程数"+threadNum+"\n") ;        message.append("开始端⼝  "+startPort+"        结束端⼝" +endPort+"\n") ;
message.append("主机名:"+getHostname(startIpStr)+"\n");
message.append("开放的端⼝如下:"+"\n") ;
for(int i = startPort;i <= endPort; i++) {
if((i + portOfThread) <= endPort) {
new Scan(i, i + portOfThread,startIpStr).start();
i += portOfThread;
}
else {
new Scan(i, endPort,startIpStr).start();
i += portOfThread;
}
}
}else{
endIpStr = Text() ;
if(checkIP(endIpStr)){
/
/扫描Ip地址段
Set ipSet = new HashSet<Object>() ;
int start = Integer.valueOf(startIpStr.split("\\.")[3]);
int end = Integer.valueOf(endIpStr.split("\\.")[3]);
String starts = startIpStr.split("\\.")[0]+"."+startIpStr.split("\\.")[1]+"."+startIpStr.split("\\.")[2];
//⽣成IP地址
for(int i = start;i<=end;i++){
ipSet.add(starts+"."+i) ;    //地海段的每个地址存⼊集合
}
for (Object str : ipSet) {
new String()).start() ;
}
}else{
JOptionPane.showMessageDialog(this, "请输⼊正确的Ip地址") ;
}
}
}
}
}
catch(NumberFormatException e1){
JOptionPane.showMessageDialog(this, "错误的端⼝号或端⼝号和线程数必须为整数") ;
}
}
else{
JOptionPane.showMessageDialog(this, "请输⼊正确的Ip地址") ;
}
}
else Source()==reset){
f_startIp.setText("") ;
f_startPort.setText("") ;
f_endPort.setText("") ;
f_portOfThread.setText("") ;
}
else Source()==clear){
message.setText("") ;
System.out.println((String) SelectedItem());
}
else Source()==exitScanner){
}else Source()==comboBox){
String type=(String) SelectedItem();
if(type.equals("地址")){
endIp.setVisible(false) ;
f_endIp.setVisible(false) ;
startIp.setText("扫描的Ip") ;
}else{
}else{
endIp.setVisible(true) ;
f_endIp.setVisible(true) ;
startIp.setText("开始Ip") ;
}
}
}
//扫描端⼝地址的线程
class Scan extends Thread{
int maxPort, minPort;
String Ip;
Scan(int minPort, int maxPort,String Ip){
this.minPort=minPort ;
this.maxPort=maxPort ;
this.Ip=Ip;
}
@SuppressWarnings("unchecked")
public  void run() {
Socket socket = null ;
for(int i = minPort;i<maxPort;i++){
java valueof
try {
socket=new Socket(Ip, i);
findInfoByPort(i ,Ip);//通过端⼝号调⽤数据库信息
message.append("\n");
socket.close();
} catch (Exception e) {
message.append("");
}
status.setText("正在扫描"+i) ;
}
status.setText("扫描结束") ;
}
}
//扫描Ip地址段查看合法Ip的线程
class ScanIp extends Thread{
String  Ip ;
ScanIp(String  Ip ){
this.Ip = Ip ;
}
public synchronized void run(){
try {
for(int i = startPort;i <= endPort; i++) {
/
/扫描开放的Ip
if((i + portOfThread) <= endPort) {
new Scan(i, i + portOfThread,Ip).start();
i += portOfThread;
}
else {
new Scan(i, endPort,Ip).start();
i += portOfThread;
}
}
} catch (Exception e) {
System.out.println(Ip+"\n");
}
}
}
//根据端⼝号,查询数据库中端⼝号的相应信息并显⽰在⽂本域之中
synchronized void findInfoByPort(int port,String Ip){
message.append("-----------------------"+"Ip"+Ip+"的"+"端⼝号"+port+"------------------------------------"+"\n");  Connection conn ;
PreparedStatement pst  ;
ResultSet rs  ;
conn = Connection() ;//与数据库建⽴连接,获取Connection对象
conn = Connection() ;//与数据库建⽴连接,获取Connection对象
String sql = "Select * from ports where port ="+port;
try {
pst = conn.prepareStatement(sql) ;
rs = uteQuery() ;
String totalStr = null ;
()){
String server = rs.getString("server");
String info = rs.getString("info") ;
message.append("端⼝信息:"+server+"\n") ;
message.append("端⼝说明:"+info+"\n") ;
totalStr =  totalStr+server ;
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 判断输⼊的IP是否合法
private boolean checkIP(String str) {
Pattern pattern = Pattern
pile("^((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]"
+ "|[*])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]|[*])$");
return pattern.matcher(str).matches();
}
//根据Ip获得主机名、
public static  synchronized String getHostname(String host){
InetAddress addr ;
try {
addr = ByName(host);
HostName();
} catch (UnknownHostException e) {
return "⽹络不通或您输⼊的信息⽆法构造InetAddress对象!";
}
}
}
数据库⼯具类
package portScanner;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public final class JdbcUtils {
private static String url = "jdbc:mysql://localhost:3306/portInfo?useUnicode=true&characterEncoding=utf8";      private static String user = "root";
private static String psw = "root";
private static  Connection conn;
static {
try {
Class.forName("sql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 获取数据库的连接
* @return conn
*/
public static Connection getConnection() {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。