概述
一、单线程扫描
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端口内容请搜索靠谱客以前的文章或继续浏览下面的相关文章希望大家以后多多支持靠谱客!
最后
以上就是酷酷冥王星为你收集整理的C# 基于TCP 实现扫描指定ip端口的方式示例的全部内容,希望文章能够帮你解决C# 基于TCP 实现扫描指定ip端口的方式示例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复