首頁 > 軟體

C#單執行緒和多執行緒埠掃描器詳解

2022-07-27 22:04:08

本文為大家分享了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#實現埠掃描器

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com