C# 基于TCP 实现扫描指定ip端口的方式示例
作者:醉意丶千层梦 发布时间:2021-11-28 07:55:24
标签:C#,扫描,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.界面
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
来源:https://blog.csdn.net/qq_47281915/article/details/121500591


猜你喜欢
- 本文实例为大家分享了Flutter Drawer抽屉菜单示例代码,供大家参考,具体内容如下一.Flutter Drawer组件简介1.源码查
- Idea2020.2创建JavaWeb的方式略有改动,以下做个记录,大家可以参考下,对以后的工作有所帮助!1.创建项目不再是Java Ent
- zuul动态路由网关服务是流量的唯一入口。不能随便停服务。所以动态路由就显得尤为必要。数据库动态路由基于事件刷新机制热修改zuul的路由属性
- 简介机器可以读,人为什么不能读?只要我们掌握java class文件的密码表,我们可以把二进制转成十六进制,将十六进制和我们的密码表进行对比
- 实际项目中pom.xml依赖写法: <dependency> <groupId>org.springf
- 先上效果图: 工具类在解析的过程中,我们会和byte做各种运算,所以我定义了一个byte工具类ByteUtils:using Sy
- C# 利用代理爬虫网页实现代码:// yanggang@mimvp.com// http://proxy.mimvp.com// 2015-
- 这一节我们先写一个简单点的Demo来测试易宝支付的流程,熟悉这个流程后,再做实际的开发,因为是一个Demo,所以我没有考虑一些设计模式的东西
- 熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最
- 如下图:点击加号添加键值对:archetypeCataloginternal补充知识:idea+maven+tomcat报404我的解决办法
- 引言在实际的Android项目开发中,图片是必不可少的元素,几乎所有的界面都是由图片构成的;像列表页、查看大图页等,都是需要展示图片,而且这
- 线程线程:对于所有需要等待的操作,例如移动文件,数据库和网络访问都需要一定的时间,此时就可以启动一个新的线程,同时完成其他任务。一个进程的多
- 本文实例讲述了Android编程实现调用相册、相机及拍照后直接裁剪的方法。分享给大家供大家参考,具体如下:package com.cvte.
- 之前自己从来没有做过发送邮箱的功能,前段时间项目需要,在找了很多帖子之后,终于实现了。之后有整理了一下,写了一个类。直接给类传递信息,就可以
- Spring security记住我基本原理:登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFil
- Android M(6.0)API 23后加入了权限请求设置,APP需要使用某些权限需要主动申请。权限分为3类,一组是Normal权限,无需
- 实践过程效果代码public partial class Form1 : Form{ public Form1()
- 为什么需要方法回调?方法回调是功能定义和功能分离的一种手段,是一种松耦合的设计思想。在JAVA中回调是通过接口来实现的。作为一种系统架构,必
- 在Google发布了support:design:23+以后我们发现有这么一个东西TextInputLayout,先看下效果图:<an
- 本节了解一下 SpringBoot 中 Web 开发的静态资源导入和首页设置,对应 SpringBoot-03-Web 项目。1. 静态资源