C#端口扫描器程序(单线程和多线程) 您所在的位置:网站首页 端口扫描程序 C#端口扫描器程序(单线程和多线程)

C#端口扫描器程序(单线程和多线程)

2023-08-19 11:46| 来源: 网络整理| 查看: 265

文章目录 一、单线程与多线程的区别二、端口扫描程序设计1. 创建项目2. 界面设计3. 单线程代码4. 多线程代码 三、端口扫描程序运行效果1. 单线程2. 多线程 四、参考

一、单线程与多线程的区别 单线程: 每个正在运行的程序(即进程),至少包括一个线程,这个线程叫主线程 主线程在程序启动时被创建,用于执行main函数 只有一个主线程的程序,称作单线程程序 主线程负责执行程序的所有代码(UI展现以及刷新,网络请求,本地存储等等)。这些代码只能顺序执行,无法并发执行多线程: 拥有多个线程的程序,称作多线程程序。 允许用户自己开辟新的线程,相对于主线程来讲,这些线程,称为子线程 可以根据需要开辟若干子线程 子线程和主线程都是独立的运行单元,各自的执行互不影响,因此能够并发执行单线程、多线程的区别: 单线程程序:只有一个线程,代码顺序执行,容易出现代码阻塞(页面假死) 多线程程序:有多个线程,线程间独立运行,能有效地避免代码阻塞,并且提高程序的运行性能 二、端口扫描程序设计 1. 创建项目 选择windows窗体应用

在这里插入图片描述

项目配置 在这里插入图片描述初始界面 在这里插入图片描述 2. 界面设计

在这里插入图片描述

3. 单线程代码 namespace ScanPort_Single { public partial class Form1 : Form { public Form1() { InitializeComponent(); System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//设置该属性 为false,将禁止捕获对错误线程的调用 } //自定义变量 //单线程 private int port;//记录当前扫描的端口号 private string Address;//记录扫描的系统地址 private bool[] done = new bool[65536];//记录端口的开放状态 private int start;//记录扫描的起始端口 private int end;//记录扫描的结束端口 private bool OK; private void button1_Click(object sender, EventArgs e) { start = Int32.Parse(textBox2.Text); end = Int32.Parse(textBox3.Text); label4.Text = start.ToString(); label6.Text = end.ToString(); label4.Visible = true; label6.Visible = true; progressBar1.Minimum = Int32.Parse(textBox2.Text); progressBar1.Maximum = Int32.Parse(textBox3.Text); listBox1.Items.Clear(); listBox1.Items.Add("端口扫描器v1.0."); listBox1.Items.Add(""); PortScan(); } private void PortScan() { //判断输入端口是否合法 if ((start >= 0 && start = 0 && end port = i; Scan(); progressBar1.Value = i; label5.Text = i.ToString(); label5.Visible = true; } while (!OK) { OK = true; for (int i = start; i OK = false; break; } } } listBox1.Items.Add("扫描结束!"); } else { MessageBox.Show("输入错误,端口范围为[0,65536]"); } } //连接端口 private void Scan() { int portnow = port; done[portnow] = true; TcpClient objTCP = null; try { objTCP = new TcpClient(Address, portnow); listBox1.Items.Add("端口" + portnow.ToString() + "开放"); } catch { } } } } 4. 多线程代码 namespace ScanPort_Single { public partial class Form1 : Form { public Form1() { InitializeComponent(); System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//设置该属性 为false,将禁止捕获对错误线程的调用 } //自定义变量 private int port;//记录当前扫描的端口号 private string Address;//记录扫描的系统地址 private bool[] done = new bool[65536];//记录端口的开放状态 private int start;//记录扫描的起始端口 private int end;//记录扫描的结束端口 private bool OK; //多线程 private Thread scanThread; private void label4_TextChanged(object sender, EventArgs e) { label4.Text = textBox2.Text; label4.Visible = true; } //将输入的结束地址放到进度条的结束位置 private void label6_TextChanged(object sender, EventArgs e) { label6.Text = textBox3.Text; label6.Visible = true; } private void button1_Click(object sender, EventArgs e) { label4_TextChanged(sender, e); label6_TextChanged(sender, e); //创建线程,并创建ThreadStart委托对象 Thread procss = new Thread(new ThreadStart(ScanPort_Thread)); procss.Start(); //显示端口扫描范围 progressBar1.Minimum = Int32.Parse(textBox2.Text); progressBar1.Maximum = Int32.Parse(textBox3.Text); listBox1.Items.Clear(); listBox1.Items.Add("端口扫描器v1.0."); listBox1.Items.Add(""); ScanPort_Thread(); } private void ScanPort_Thread() { start = Int32.Parse(textBox2.Text); end = Int32.Parse(textBox3.Text); //判断输入端口是否合法 if ((start >= 0 && start = 0 && end port = i; //对该端口进行扫描的线程 scanThread = new Thread(Scan); scanThread.Start(); //使线程睡眠 System.Threading.Thread.Sleep(100); progressBar1.Value = i; label5.Text = i.ToString(); label5.Visible = true; } //未完成时情况 while (!OK) { OK = true; for (int i = start; i OK = false; break; } } } listBox1.Items.Add("扫描结束!"); System.Threading.Thread.Sleep(1000); } else { MessageBox.Show("输入错误,端口范围为[0,65536]"); } } //连接端口 private void Scan() { int portnow = port; //创建线程变量 Thread Threadnow = scanThread; done[portnow] = true; //创建TcpClient对象,TcpClient用于TCP网络服务提供客户端连接 TcpClient objTCP = null; //扫描端口,成功就写入信息 try { objTCP = new TcpClient(Address, portnow); listBox1.Items.Add("端口" + portnow.ToString() + "开放!"); } catch { } } private void Form1_Load(object sender, EventArgs e) { } private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { } } }

说明:当使用多线程功能时,在子线程里修改UI控件参数时,会报错

异常:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“listBox1”的线程访问它。”

解决办法在Form1重载中写上一行代码

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//设置该属性 为false,将禁止捕获对错误线程的调用

也可以

listBox1.Invoke(new EventHandler(delegate { //其他线程创建的控件的参数的一些修改语句 })); 三、端口扫描程序运行效果 1. 单线程

在这里插入图片描述

2. 多线程

在这里插入图片描述 在这里插入图片描述 整个过程使用多个线程来实现扫描端口,次线程的进行并不会影响主线程的进行,线程之间不会相互影响。 对比单线程,多线程时间明显更短,单线程会出现卡顿的情况,而多线程的方式不会产生卡顿。

四、参考

https://blog.csdn.net/RSpcc/article/details/109805738



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有