C#_窗体应用项目_多线程IP地址扫描

多线程IP地址扫描

窗体展示

主窗体

代码参考

//From:TengMMVP
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Net;
using System.Threading;
using System.Windows.Forms;

namespace IPAdressForm
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            //初始化窗体
            InitializeComponent();
            //默认隐藏提示标签
            label_Tip.Visible = false;
        }

        //鼠标事件:“单线程”按钮被点击
        private void button_SingleThread_Click(object sender, EventArgs e)
        {
            //如果“单线程”按钮被点击,调用启动扫描函数,传参“false”
            RunScan(isMultithreaded: false);
        }

        //鼠标事件:“多线程”按钮被点击
        private void button_MultiThread_Click(object sender, EventArgs e)
        {
            //如果“多线程”按钮被点击,调用启动扫描函数,传参“true”
            RunScan(isMultithreaded: true);
        }

        //启动扫描函数:首先进行扫描前的预处理,然后根据参数调用具体的扫描函数进行扫描
        private void RunScan(bool isMultithreaded)
        {
            //创建了一个新线程来执行扫描操作
            new Thread(() =>
            {
                //使用 `Invoke` 方法在主线程上执行清除 `textBox_Show` 的内容
                Action clearAction = () => textBox_Show.Clear();
                Invoke(clearAction);

                //扫描预处理一:IP地址前缀合法性检查
                string ipPrefix = textBox_IPAdressPre.Text;
                if (!IsValidIpPrefix(ipPrefix))
                {
                    ShowTip("IP地址前缀不合法。");
                    return;
                }

                //扫描预处理二:起始值/终止值合法性检查。
                if (!int.TryParse(textBox_Start.Text, out int start) || !int.TryParse(textBox_End.Text, out int end) || start < 0 || end < start || start > 255 || end > 255)
                {
                    ShowTip("起始或终止值不合法。");
                    return;
                }

                Action HideAction = () => label_Tip.Visible = false;
                Invoke(HideAction);

                //创建一个停表并启动,用于记录总扫描时间
                Stopwatch totalStopwatch = new Stopwatch();
                totalStopwatch.Start();


                if (isMultithreaded)//如果是多线程则运行下面的代码段
                {
                    // 创建一个Thread类型的列表threads,用于存储线程
                    List<Thread> threads = new List<Thread>();

                    for (int i = start; i <= end; i++)
                    {
                        // 将ipPrefix字符串与循环变量i拼接,构造出IP地址
                        string ip = ipPrefix + i;
                        // 创建一个新线程,线程的工作是调用ScanIp方法并传入构造的IP地址
                        Thread thread = new Thread(() => ScanIp(ip));
                        threads.Add(thread);
                        // 启动新创建的线程
                        thread.Start();
                    }

                    // 遍历threads列表中的每个线程
                    foreach (Thread thread in threads)
                    {
                        //调用Join方法,等待当前遍历到的线程执行完毕
                        thread.Join();
                    }
                }
                else//如果是单线程则运行下面的代码段
                {
                    for (int i = start; i <= end; i++)
                    {
                        string ip = ipPrefix + i;
                        // 在单线程模式下直接顺序执行
                        ScanIp(ip); 
                    }
                }

                //扫描完毕,停表计时结束
                totalStopwatch.Stop();

                //使用 `Invoke` 方法在主线程上更新 `textBox_Show`,显示总扫描时间
                Invoke((MethodInvoker)delegate
                {
                    textBox_Show.AppendText($"总扫描时间:{totalStopwatch.ElapsedMilliseconds}毫秒\n");
                });

            })
            { IsBackground = true }.Start();//设置为后台进程并启动
        }

        //初步判断输入的IP地址前缀是否合法的具体实现
        private bool IsValidIpPrefix(string ipPrefix)
        {
            //采用正则表达式来判断
            return System.Text.RegularExpressions.Regex.IsMatch(ipPrefix, @"^(\d{1,3}\.){3}$");
        }

        //IP扫描的具体实现
        private void ScanIp(string ip)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            string result;
            try
            {
                IPHostEntry hostEntry = Dns.GetHostEntry(ip);
                stopwatch.Stop();
                result = $"扫描地址:{ip},扫描用时:{stopwatch.ElapsedMilliseconds}毫秒,主机DNS名称:{hostEntry.HostName}\r\n";
            }
            catch
            {
                stopwatch.Stop();
                result = $"扫描地址:{ip},扫描用时:{stopwatch.ElapsedMilliseconds}毫秒,异常:查询不到主机\r\n";
            }

            //更新界面结果
            Invoke((MethodInvoker)delegate { UpdateUI(result); });
        }

        //更新UI界面的具体实现
        private void UpdateUI(string text)
        {
            // 检查textBox_Show控件的InvokeRequired属性  
            // 如果为true,说明当前线程不是创建textBox_Show的线程(通常是UI线程)  
            // 因此需要使用Invoke方法来在UI线程上执行更新操作 
            if (textBox_Show.InvokeRequired)
            {
                // 使用Lambda表达式创建一个无参数的Action委托  
                // 该委托调用textBox_Show的AppendText方法来追加文本  
                // 然后通过Invoke方法在UI线程上执行这个委托 
                textBox_Show.Invoke(new Action(() => textBox_Show.AppendText(text)));
            }
            else
            {
                // 如果当前线程就是UI线程,则直接调用AppendText方法来追加文本
                textBox_Show.AppendText(text);
            }
        }

        //提示标签处理
        private void ShowTip(string message)
        {
            if (label_Tip.InvokeRequired)
            {
                label_Tip.Invoke(new Action(() =>
                {
                    label_Tip.Text = message;
                    label_Tip.BackColor = Color.Red;
                    label_Tip.Visible = true;
                }));
            }
            else
            {
                label_Tip.Text = message;
                label_Tip.BackColor = Color.Red;
                label_Tip.Visible = true;
            }
        }
    }
}
//From:TengMMVP

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值