C# 基于TCP 实现扫描指定ip端口的方式示例

作者:醉意丶千层梦 时间:2021-11-28 07:55:24 

一、单线程扫描

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.界面

C# 基于TCP 实现扫描指定ip端口的方式示例

3.结果

由于是单线程执行,在扫描端口的时候程序会直接卡死。所以只简单扫描几个端口

C# 基于TCP 实现扫描指定ip端口的方式示例

4.抓包

由于是通过以太网发送的,建议先注销哆点再进行抓包,减少数据。
可以发现3900端口成功实现三次握手,即该端口是开放的。而其他端口(红色)则是无法建立连接,意味着是关闭的。

C# 基于TCP 实现扫描指定ip端口的方式示例

二、多线程扫描

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.界面

C# 基于TCP 实现扫描指定ip端口的方式示例

3.结果

不会出现单线程的卡死,扫描速度也大大提升。同时可以随时开始和暂停操作。

C# 基于TCP 实现扫描指定ip端口的方式示例

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

来源:https://blog.csdn.net/qq_47281915/article/details/121500591

标签:C#,扫描,ip端口
0
投稿

猜你喜欢

  • 身份证号码验证算法深入研究和Java实现

    2023-05-18 08:17:42
  • 详解Spring中的Environment外部化配置管理

    2023-11-23 05:24:24
  • Java多线程死锁与资源限制操作

    2023-08-31 05:54:30
  • SpringBoot 多Profile使用与切换方式

    2022-04-13 14:58:27
  • 分享WCF聊天程序--WCFChat实现代码

    2023-01-19 17:04:59
  • C#异步调用实例小结

    2023-07-16 10:31:03
  • java日期时间操作工具类

    2022-09-03 13:04:58
  • 浅谈Java中向上造型向下造型和接口回调中的问题

    2023-11-09 13:51:46
  • Java中synchronized的几种使用方法

    2023-06-19 16:33:28
  • 利用AOP实现SqlSugar自动事务

    2021-11-24 11:56:42
  • Spring Boot应用程序同时支持HTTP和HTTPS协议的实现方法

    2022-01-10 16:50:43
  • springboot项目配置swagger2示例详解

    2021-09-01 04:24:47
  • 关于C#操作文件路径(Directory)的常用静态方法详解

    2023-06-06 10:40:12
  • SpringBoot使用Jackson配置全局时间日期格式

    2021-10-04 12:45:06
  • Spring Security自定义登录原理及实现详解

    2022-11-20 21:57:39
  • Unity2019-2020 个人版官方免费激活详细方法

    2023-12-08 21:57:39
  • 图解Java线程的生命周期

    2022-04-12 15:16:10
  • Java中的传值与传引用实现过程解析

    2023-02-21 12:59:41
  • jvm crash的崩溃日志详细分析及注意点

    2022-12-18 07:49:00
  • 谈谈你可能并不了解的java枚举

    2023-11-09 21:08:55
  • asp之家 软件编程 m.aspxhome.com