基于C#实现端口扫描器(单线程和多线程)
作者:Baker_Streets 发布时间:2021-10-16 20:32:23
标签:C#,端口,扫描
一、新建项目并设置界面
新建项目:
选择Windows窗体项目应用(.Net Framework):
设置项目名和路径:
新建项目如下:
设置界面:
将tbShow设置为只读:
二、单线程实现端口扫描
1. 编写代码
双击按钮,编写其点击事件:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Scan
{
public partial class Form1 : Form
{
//主机地址
private string hostAddress;
//起始端口
private int start;
//终止端口
private int end;
//端口号
private int port;
//定义线程对象
private Thread scanThread;
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
try
{
//初始化
tbShow.Clear();
lb.Text = "0%";
//获取ip地址和始末端口号
hostAddress = tbHost.Text;
start = Int32.Parse(tbSPort.Text);
end = Int32.Parse(tbEPort.Text);
if (decideAddress()) // 端口合理
{
//让输入的textbox只读,无法改变
tbHost.ReadOnly = true;
tbSPort.ReadOnly = true;
tbEPort.ReadOnly = true;
//设置进度条的范围
pb.Minimum = start;
pb.Maximum = end;
//显示框显示
tbShow.AppendText("端口扫描器 v1.0.0" + Environment.NewLine + Environment.NewLine);
//调用端口扫描函数
PortScan();
}
else
{
//若端口号不合理,弹窗报错
MessageBox.Show("输入错误,端口范围为[0-65536]!");
}
}
catch
{
//若输入的端口号为非整型,则弹窗报错
MessageBox.Show("输入错误,端口范围为[0-65536]!");
}
}
/// <summary>
/// 判断端口是否合理
/// </summary>
/// <returns></returns>
private bool decideAddress()
{
//判断端口号是否合理
if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end))
return true;
else
return false;
}
private void PortScan()
{
double x;
string xian;
//显示扫描状态
tbShow.AppendText("开始扫描...(可能需要请您等待几分钟)" + Environment.NewLine + Environment.NewLine);
//循环抛出线程扫描端口
for (int i = start; i <= end; i++)
{
x = (double)(i - start + 1) / (end - start + 1);
xian = x.ToString("0%");
port = i;
//调用端口i的扫描操作
Scan();
//进度条值改变
lb.Text = xian;
lb.Refresh();
pb.Value = i;
}
tbShow.AppendText(Environment.NewLine + "扫描结束!" + Environment.NewLine);
//输入框textbox只读属性取消
tbHost.ReadOnly = false;
tbSPort.ReadOnly = false;
tbEPort.ReadOnly = false;
}
/// <summary>
/// 扫描某个端口
/// </summary>
private void Scan()
{
int portnow = port;
//创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接
TcpClient objTCP = null;
try
{
//用于TcpClient对象扫描端口
objTCP = new TcpClient(hostAddress, portnow);
//扫描到则显示到显示框
tbShow.AppendText("端口 " + port + " 开放!" + Environment.NewLine);
}
catch
{
//未扫描到,则会抛出错误
}
}
}
}
2. 运行结果
可发现速度十分缓慢,且不能拖拽。
三、多线程实现端口扫描
1. 编写代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Scan
{
public partial class Form1 : Form
{
//主机地址
private string hostAddress;
//起始端口
private int start;
//终止端口
private int end;
//端口号
private int port;
//定义线程对象
private Thread scanThread;
//定义端口状态数据(开放则为true,否则为false)
private bool[] done = new bool[65526];
private bool OK;
public Form1()
{
InitializeComponent();
//不进行跨线程检查
CheckForIllegalCrossThreadCalls = false;
}
private void button1_Click_1(object sender, EventArgs e)
{
try
{
//初始化
tbShow.Clear();
lb.Text = "0%";
//获取ip地址和始末端口号
hostAddress = tbHost.Text;
start = Int32.Parse(tbSPort.Text);
end = Int32.Parse(tbEPort.Text);
if (decideAddress()) // 端口合理
{
//让输入的textbox只读,无法改变
tbHost.ReadOnly = true;
tbSPort.ReadOnly = true;
tbEPort.ReadOnly = true;
//创建线程,并创建ThreadStart委托对象
Thread process = new Thread(new ThreadStart(PortScan));
process.Start();
//设置进度条的范围
pb.Minimum = start;
pb.Maximum = end;
//显示框显示
tbShow.AppendText("端口扫描器 v1.0.0" + Environment.NewLine + Environment.NewLine);
}
else
{
//若端口号不合理,弹窗报错
MessageBox.Show("输入错误,端口范围为[0-65536]!");
}
}
catch
{
//若输入的端口号为非整型,则弹窗报错
MessageBox.Show("输入错误,端口范围为[0-65536]!");
}
}
/// <summary>
/// 判断端口是否合理
/// </summary>
/// <returns></returns>
private bool decideAddress()
{
//判断端口号是否合理
if ((start >= 0 && start <= 65536) && (end >= 0 && end <= 65536) && (start <= end))
return true;
else
return false;
}
private void PortScan()
{
double x;
string xian;
//显示扫描状态
tbShow.AppendText("开始扫描...(可能需要请您等待几分钟)" + Environment.NewLine + Environment.NewLine);
//循环抛出线程扫描端口
for (int i = start; i <= end; i++)
{
x = (double)(i - start + 1) / (end - start + 1);
xian = x.ToString("0%");
port = i;
//使用该端口的扫描线程
scanThread = new Thread(new ThreadStart(Scan));
scanThread.Start();
//使线程睡眠
System.Threading.Thread.Sleep(100);
//进度条值改变
lb.Text = xian;
pb.Value = i;
}
while (!OK)
{
OK = true;
for (int i = start; i <= end; i++)
{
if (!done[i])
{
OK = false;
break;
}
}
System.Threading.Thread.Sleep(1000);
}
tbShow.AppendText(Environment.NewLine + "扫描结束!" + Environment.NewLine);
//输入框textbox只读属性取消
tbHost.ReadOnly = false;
tbSPort.ReadOnly = false;
tbEPort.ReadOnly = false;
}
/// <summary>
/// 扫描某个端口
/// </summary>
private void Scan()
{
int portnow = port;
//创建线程变量
Thread Threadnow = scanThread;
//扫描端口,成功则写入信息
done[portnow] = true;
//创建TcpClient对象,TcpClient用于为TCP网络服务提供客户端连接
TcpClient objTCP = null;
try
{
//用于TcpClient对象扫描端口
objTCP = new TcpClient(hostAddress, portnow);
//扫描到则显示到显示框
tbShow.AppendText("端口 " + port + " 开放!" + Environment.NewLine);
}
catch
{
//未扫描到,则会抛出错误
}
}
}
}
2. 运行结果
可发现速度明显变快,且能拖拽窗口。
四、总结
多线程可以提高CPU的利用率。
参考
C#单线程和多线程的应用比较:端口扫描器
来源:https://blog.csdn.net/weixin_46628481/article/details/121440214
0
投稿
猜你喜欢
- 目录1、需求2、问题2、获取1)导入依赖为了获取客户端类型、操作系统类型、ip、port2)封装获取body字符串的工具类3) * 类4)继
- 前言如果你想玩转C# 里面多线程,工厂模式,生产者/消费者,队列等高级操作,就可以和我一起探索这个强大的线程安全提供阻塞和限制功能的C#神器
- Java 8新特性方法引用对于引用来说我们一般都是用在对象,而对象引用的特点是:不同的引用对象可以操作同一块内容!Java 8的方法引用定义
- 本文探讨使用C# StringBuilder 的最佳实践,用于减少内存分配,提高字符串操作的性能。在 .NET 中,String 对象是不可
- 现象: 1. 表面现象: 方法中输出的日志, 日志文件中找不到, 也没有任何报错(即@Async标注的方法没有执行, 也没有报错)2. 分析
- 1.代码:import java.math.BigDecimal;import java.text.DecimalFormat;import
- 本文实例讲述了C#基于OLEDB获取Excel文件表结构信息的方法。分享给大家供大家参考,具体如下:这个问题来自论坛提问,同理可以获得acc
- 项目开发中对于一些数据的处理需要用到多线程,比如文件的批量上传,数据库的分批写入,大文件的分段下载等。 通常会使用spring自带的线程池处
- 本文实例为大家分享了JavaWeb实现简单文件上传的具体代码,供大家参考,具体内容如下1.概述通常浏览器上传的所有参数,我们可以通过requ
- 一、ListView该组件是android中最常用的一个UI组件,用于实现在屏幕上显示多个内容,以便于我们用手指来回翻转。先在layout中
- 具体代码如下所示:public class MainActivity extends AppCompatActivity { p
- 问题描述输入一个链表,输出该链表中倒数第k个结点。(尾结点是倒数第一个)结点定义如下:public class ListNode { &nb
- 本文实例为大家分享了利用Swing绘制一个动态时钟的具体代码,供大家参考,具体内容如下效果代码在下面,可跳过解析。前言编程实现一个时钟利用S
- 今天工作中遇到一个需求,就是获取 excel 里面的内容,并且把 excel 另存为 csv,因为本人以前未接触过,所以下面整理出来的代码均
- 需要装一个插件:File - Settings- Plugins - 搜索gson 安装GsonFromat;如下两张图安装完成后 ,新建一
- 目录前言Hello World1.可以在 Spring Initializr上面添加,也可以手动在 pom.xml中添加如下代码∶2. 编写
- 在分支较多的时候,switch的效率比if高,在反汇编中我们即可看到效率高的原因一、switch语句1、在正向编码时,switch语句可以看
- 创建一个maven项目导入springboot依赖,注意底 * 释部分<?xml version="1.0&quo
- Android IPC机制Messenger实例详解前言:Messenger可以翻译成信使,通过它可以在不同进程间传递Message对象有了
- 本文实例讲述了java实现单词搜索迷宫游戏。分享给大家供大家参考。具体分析如下:我们在杂志上,经常能够看到找单词的小游戏,在一个二维表格中,