C#单线程和多线程端口扫描器详解

目录

一、项目创建以及页面设计

(一)项目新建

(二)页面设计

二、单线程实现端口扫描

(一)代码实现

(二)运行结果

三、多线程实现端口扫描

(一)程序实现

(二)运行结果

四、总结

五、参考资料

本文为大家分享了C#单线程和多线程端口扫描器,供大家参考,具体内容如下

一、项目创建以及页面设计 (一)项目新建

1.选择Windows窗体项目应用(.Net Framework)->下一步:

2.项目命名以及合适的存储位置,选择创建

(二)页面设计

1.点开工具箱,需要4个Label,一个Button,一个Progress,4个TextBox

2.横向拉伸TextBox

(1)点击三角形

(2)勾选Multiline后拉伸

(3)设置控件的名称和唯一标志

设置唯一标志

修改显示名称

(4)页面设计如下

(5)设置消息显示界面的 TextBox 不可编辑:找到 Enabled 属性,参数设为 False 。

二、单线程实现端口扫描 (一)代码实现

1.双击按钮btnShow

2.编写代码

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 cqjtuWindowsFormsApp {     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 label1_Click(object sender, EventArgs e)             {             }             private void label2_Click(object sender, EventArgs e)             {             }             private void label4_Click(object sender, EventArgs e)             {             }             private void button1_Click(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                 {                     //未扫描到,则会抛出错误                 }             }         } } (二)运行结果

1.启动项目

2.输入相关信息

3.扫描结果

三、多线程实现端口扫描 (一)程序实现 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 cqjtuWindowsFormsApp {     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 label1_Click(object sender, EventArgs e)             {             }             private void label2_Click(object sender, EventArgs e)             {             }             private void label4_Click(object sender, EventArgs e)             {             }             private void button1_Click(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             {                 //未扫描到,则会抛出错误             }             }         } } (二)运行结果

1.启动项目

2.输入相关信息

3.扫描结果

可以发现多线程扫描只需要十几秒,而单线程需要几分钟,明显多线程比单线程更快些

四、总结

可以发现多线程能够有更好的CPU使用率,可以使程序设计更简单,明显可以看见多线程拥有更快的程序响应速度。

五、参考资料

C#实现端口扫描器

推荐阅读

    设置线程名称|tomcat线程名称设置

    设置线程名称|tomcat线程名称设置,,1. tomcat线程名称设置一.tomcat的优化1.tomcat的自身调优采用动静分离调优Tomcat线程池调优Tomcat的

    多线程cpu电脑|多线程的CPU

    多线程cpu电脑|多线程的CPU,,1. 多线程的CPU四核心四线程,表示这个电脑的CPU核心是4个核心、4个线程的。电脑CPU的核心数量和线程数量越多,

    简单的线程池(三)

    简单的线程池(三),吞吐量,线程,◆ 概要本文中,作者针对 《简单的线程池(一)》 和 《简单的线程池(二)》 介绍的两个线程池分别进行了并发测试。基

    foreach的用法c语言和c#

    foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语言和c#详细讲解foreach循环的用法C#中的foreach 怎么用啊foreach用法C#中的f

    Common Lisp支持多线程吗

    Common Lisp支持多线程吗,语言,都是,本文目录Common Lisp支持多线程吗能推荐下比较经典的common lisp 代码么相比Scheme 与 Common Lisp,Cl