首頁 > 軟體

C# 基於TCP 實現掃描指定ip埠的方式範例

2021-11-25 13:00:11

一、單執行緒掃描

1.程式碼

using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SingleThreadScanningPort
{
    public partial class Form1 : Form
    {
        
        private bool[] ports = new bool[65536];//所有埠號
        private static int port=0;//當前埠號
        private static int count = 0;//開放埠號數量

        public Form1()
        {
            InitializeComponent();
            //CheckForIllegalCrossThreadCalls設定為false;然後就能安全的存取表單控制元件
            CheckForIllegalCrossThreadCalls = false;

            //初始化進度顯示為空
            label2.Text = "";

            //停止掃描按鈕為不可用
            stopScanning.Enabled = false;
        }

        private void beginScanning_Click(object sender, EventArgs e)
        {
            //檢查埠號
            if (int.Parse(beginPortText.Text) < 0 || int.Parse(beginPortText.Text) > int.Parse(endPortText.Text) || int.Parse(endPortText.Text) > 65565)
            {
                messages.Items.Add("埠錯誤!");
                return;
            }

            //新建執行緒執行掃描埠函數
            Thread procss = new Thread(new ThreadStart(ScanningPort));
            procss.Start();

            //設定進度條最大值最小值分別為結束埠和起始埠
            progressBar1.Maximum = int.Parse(endPortText.Text) - int.Parse(beginPortText.Text);
            progressBar1.Minimum = 0;

            //判斷是否為繼續掃描
            if (port == 0)
            {
                messages.Items.Clear();
                messages.Items.Add("開始掃描.......");
            }

            else
                messages.Items.Add("繼續掃描......");

            //開始掃描禁用,停止掃描啟用
            beginScanning.Enabled = false;
            stopScanning.Enabled = true;
        }
        public void ScanningPort()
        {
            int start;
            int end = int.Parse(endPortText.Text);

            //判斷是否為繼續掃描,如果是則繼續掃描,否則重新掃描
            if (port != 0)
                start = port;
            else
                start = int.Parse(beginPortText.Text);

            messages.Items.Add("起始埠" + start);
            messages.Items.Add("結束埠" + end);


            for (int i = start; i <= end; i++)
            {

                //按下停止掃描後開始掃描按鈕啟用,此時停止掃描
                if (beginScanning.Enabled)
                    break;
                port = i;

                //新建執行緒進行掃描
                Thread thread = new Thread(Scanning);
                thread.Start();

                //主執行緒休眠10ms
                System.Threading.Thread.Sleep(10);

                //修改進度條的值
                progressBar1.Value = i- int.Parse(beginPortText.Text);

                //顯示埠號以及進度
                label2.Text = "正在掃描埠: " + i+"  進度: "+Math.Round(( (i - int.Parse(beginPortText.Text)) *100.0 / progressBar1.Maximum),2)+"%";
                progressBar1.PerformStep();
            }

            if (port != 0)
                beginScanning.Text = "繼續掃描";
            else
            {
                messages.Items.Add("埠掃描結束");
                messages.Items.Add("共有 " + count + " 個埠開放");
            }

            beginScanning.Enabled = true;
            stopScanning.Enabled = false;
           

            //判斷是否掃描完畢
            if (int.Parse(endPortText.Text) == port)
            {
                port = 0;
                beginScanning.Text = "開始掃描";
            }

        }


        public void Scanning()
        {
            this.ports[port] = true;
            try
            {
                TcpClient tmp = new TcpClient(ipAddressText.Text, port);
                messages.Items.Add("埠" + port + "開放");
                count++;
            }

            catch (System.Exception ex)
            {
               
            }
        }

        private void stopScanning_Click(object sender, EventArgs e)
        {
            //按下停止按鈕後,開始按鈕和停止按鈕狀態翻轉
            beginScanning.Enabled = true;
            stopScanning.Enabled = false;
        }
    }
}

2.介面

3.結果

由於是單執行緒執行,在掃描埠的時候程式會直接卡死。所以只簡單掃描幾個埠

4.抓包

由於是通過乙太網傳送的,建議先登出哆點再進行抓包,減少資料。
可以發現3900埠成功實現三次握手,即該埠是開放的。而其他埠(紅色)則是無法建立連線,意味著是關閉的。

二、多執行緒掃描

1.程式碼

using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SingleThreadScanningPort
{
    public partial class Form1 : Form
    {
        
        private bool[] ports = new bool[65536];//所有埠號
        private static int port=0;//當前埠號
        private static int count = 0;//開放埠號數量

        public Form1()
        {
            InitializeComponent();
            //CheckForIllegalCrossThreadCalls設定為false;然後就能安全的存取表單控制元件
            CheckForIllegalCrossThreadCalls = false;

            //初始化進度顯示為空
            label2.Text = "";

            //停止掃描按鈕為不可用
            stopScanning.Enabled = false;
        }

        private void beginScanning_Click(object sender, EventArgs e)
        {
            //檢查埠號
            if (int.Parse(beginPortText.Text) < 0 || int.Parse(beginPortText.Text) > int.Parse(endPortText.Text) || int.Parse(endPortText.Text) > 65565)
            {
                messages.Items.Add("埠錯誤!");
                return;
            }

            //新建執行緒執行掃描埠函數
            Thread procss = new Thread(new ThreadStart(ScanningPort));
            procss.Start();

            //設定進度條最大值最小值分別為結束埠和起始埠
            progressBar1.Maximum = int.Parse(endPortText.Text) - int.Parse(beginPortText.Text);
            progressBar1.Minimum = 0;

            //判斷是否為繼續掃描
            if (port == 0)
            {
                messages.Items.Clear();
                messages.Items.Add("開始掃描.......");
            }

            else
                messages.Items.Add("繼續掃描......");

            //開始掃描禁用,停止掃描啟用
            beginScanning.Enabled = false;
            stopScanning.Enabled = true;
        }
        public void ScanningPort()
        {
            int start;
            int end = int.Parse(endPortText.Text);

            //判斷是否為繼續掃描,如果是則繼續掃描,否則重新掃描
            if (port != 0)
                start = port;
            else
                start = int.Parse(beginPortText.Text);

            messages.Items.Add("起始埠" + start);
            messages.Items.Add("結束埠" + end);


            for (int i = start; i <= end; i++)
            {

                //按下停止掃描後開始掃描按鈕啟用,此時停止掃描
                if (beginScanning.Enabled)
                    break;
                port = i;

                //新建執行緒進行掃描
                Thread thread = new Thread(Scanning);
                thread.Start();

                //主執行緒休眠10ms
                System.Threading.Thread.Sleep(10);

                //修改進度條的值
                progressBar1.Value = i- int.Parse(beginPortText.Text);

                //顯示埠號以及進度
                label2.Text = "正在掃描埠: " + i+"  進度: "+Math.Round(( (i - int.Parse(beginPortText.Text)) *100.0 / progressBar1.Maximum),2)+"%";
                progressBar1.PerformStep();
            }

            if (port != 0)
                beginScanning.Text = "繼續掃描";
            else
            {
                messages.Items.Add("埠掃描結束");
                messages.Items.Add("共有 " + count + " 個埠開放");
            }

            beginScanning.Enabled = true;
            stopScanning.Enabled = false;
           

            //判斷是否掃描完畢
            if (int.Parse(endPortText.Text) == port)
            {
                port = 0;
                beginScanning.Text = "開始掃描";
            }

        }


        public void Scanning()
        {
            this.ports[port] = true;
            try
            {
                TcpClient tmp = new TcpClient(ipAddressText.Text, port);
                messages.Items.Add("埠" + port + "開放");
                count++;
            }

            catch (System.Exception ex)
            {
               
            }
        }

        private void stopScanning_Click(object sender, EventArgs e)
        {
            //按下停止按鈕後,開始按鈕和停止按鈕狀態翻轉
            beginScanning.Enabled = true;
            stopScanning.Enabled = false;
        }
    }
}

2.介面

3.結果

不會出現單執行緒的卡死,掃描速度也大大提升。同時可以隨時開始和暫停操作。

4.抓包

和單執行緒的抓包思路以及結果都是一樣的

三、總結

單執行緒操作的時候會出現介面直接卡死並且掃描速度很慢,
多執行緒操作掃描速度大大提升而且不會出現介面卡死。

四、原始碼

1.github

https://github.com/TangtangSix/SingleThreadScanningPort

https://github.com/TangtangSix/MultithreadingScanningPort

2.gitee

https://gitee.com/tangtangsix/SingleThreadScanningPort
https://gitee.com/tangtangsix/MultithreadingScanningPort

到此這篇關於C# 基於TCP 實現掃描指定ip埠的方式範例的文章就介紹到這了,更多相關C# 掃描指定ip埠內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


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