C#之单线程,多线程,线程池程序设计扫描网络IP
2013-01-23 15:22
447 查看
单线程,多线程,线程池程序设计扫描网络IP
创建一个Windows应用程序,使用多线程等来扫描一个网段内的计算机,根据计算机的IP地址获取其Dns域名,若计算机不在线,则返回提示信息。要求初始界面如图所示。当用户输入IP地址范围之后,单击【扫描】按钮,程序能自动在listBoxStatus中显示每个IP地址对应的Dns信息。具体要求如下:
(1)对用户选择IP地址范围进行验证,若不是合法的IP地址,给出相应的提示信息。
(2)执行扫描操作时,创建一个线程去扫描一个IP地址。
(3)把每个IP地址对应的Dns信息添加到listBoxStatus中。例如采用“IP地址---Dns域名”形式。
实验要求
(1)要求用ipCount表示IP地址的个数;
(2)要求用start表示IP起始地址,end表示IP终止地址。
2.实验步骤
(1)运行Microsoft Visual Studio 2008,创建一个名为ScanComputer的Windows应用程序项目。
(2)在【解决方案资源管理器】中,设计界面如图1-1所示。
(3)切换到代码模式,在Form1.cs文件namespace ScanComputer下定义一个委托。
public delegate void GetComputerDnsDelegate(string strIP,string strHostName);
其中strIP用来表示IP地址,strHostName用来表示IP对应的Dns名字。
(4)在类Form1.cs中定义并实现方法AddStatusInfoToListBox用来实现向listBoxStatus添加扫描信息。
方法形式:public void AddStatusInfoToListBox(string strIP, string strHostName)
(5)为了实现给线程传递多个参数,在namespace ScanComputer下定义一个类Scan,用来保存参数和提供方法实现IP地址到Dns的转换。其中方法CheckComputer实现IP到Dns的转换。
(6)在【扫描】按钮的Click事件中,先判断IP地址范围是否符合要求,然后统计要计算IP的个数,创建多个线程去执行扫描操作。
程序运行图:
(1)单线程
(2)多线程
(3)线程池
源程序代码:
类Scan:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Windows.Forms; namespace ScanComputer { class Scan { public string strIp; public ScanComputer.Form1.GetComputerDnsDelegate d; public string HostName; public void CheckComputer() { IPAddress ip; IPHostEntry ipe; try { ip = IPAddress.Parse(this.strIp); ipe = Dns.GetHostEntry(ip); HostName = ipe.HostName; } catch { HostName = "未响应!"; } if (d != null) { d(strIp, HostName); } } public void CheckComputerStr(Object stateInfo) { this.strIp = (string)stateInfo; CheckComputer(); } } } Form1.cs namespace ScanComputer { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public int ipCount; public int start; public int end; public string subIP; public int hasEndCount;//用于判断线程是否都已结束 public delegate void GetComputerDnsDelegate(string strIP, string strHostName); public void AddStatusInfoToListBox(string strIP, string strHostName) { if (this.listBoxStatus.InvokeRequired) { GetComputerDnsDelegate d = AddStatusInfoToListBox; listBoxStatus.Invoke(d,strIP,strHostName); } else { hasEndCount++; listBoxStatus.Items.Add(strIP + "---域名:" + strHostName); if (hasEndCount == ipCount) { endTime = DateTime.Now; TimeSpan tm =endTime - startTime; listBoxStatus.Items.Add("----------------------"); listBoxStatus.Items.Add("扫描完毕,用时:" + tm.Milliseconds+"毫秒"); this.buttonScanSingle.Enabled = true; this.buttonScanAgain.Enabled = true; this.buttonScanPool.Enabled = true; } } } DateTime startTime, endTime; IPAddress ip; IPHostEntry ipe; string strIp, hostName; /// <summary> /// 多线程扫描 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonScanAgain_Click(object sender, EventArgs e) { Init();//初始化操作 if (ipCount < 0) { MessageBox.Show("起始地址和终止地址有错误,请检查后再次扫描。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Question); return; } Thread[] scanThreads = new Thread[ipCount]; //定义Scan实例 Scan scanObj; for (int i = 0; i < ipCount; i++) { scanObj = new Scan(); //传递ip地址 scanObj.strIp = subIP + (numericUpDownIpStart.Value + i).ToString(); scanObj.d = AddStatusInfoToListBox; //初始化线程实例 scanThreads[i] = new Thread(scanObj.CheckComputer); //启动线程 scanThreads[i].Start(); } } /// <summary> /// 单线程 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonScanSingle_Click(object sender, EventArgs e) { //初始化IP范围 Init(); if (ipCount <0) { MessageBox.Show("起始地址和终止地址有错误,请检查后再次扫描。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Question); return; } Thread thread = new Thread(SingleThread); thread.Start(); } private void SingleThread() { for (int i = 0; i < ipCount; i++) { strIp = subIP + (numericUpDownIpStart.Value + i).ToString(); try { ip = IPAddress.Parse(strIp); ipe = Dns.GetHostEntry(ip); hostName = ipe.HostName; AddStatusInfoToListBox(strIp, hostName); } catch { AddStatusInfoToListBox(strIp, "未响应!"); } } } /// <summary> /// 线程池扫描 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonScanPool_Click(object sender, EventArgs e) { Init(); Scan scanObj; for (int i = 0; i < ipCount; i++) { scanObj = new Scan(); //传递ip地址 scanObj.strIp = subIP + (numericUpDownIpStart.Value + i).ToString(); scanObj.d = AddStatusInfoToListBox; //将任务加入线程队列 ThreadPool.QueueUserWorkItem(scanObj.CheckComputerStr, scanObj.strIp); } } /// <summary> /// IP地址范围计算 /// </summary> private void Init() { startTime = DateTime.Now; this.listBoxStatus.Items.Clear(); this.buttonScanAgain.Enabled = false; this.buttonScanSingle.Enabled = false; this.buttonScanPool.Enabled = false; subIP = numericUpDownIp1.Value + "." + numericUpDownIp2.Value + "." + numericUpDownIp3.Value+"."; start = (int)numericUpDownIpStart.Value; end = (int)numericUpDownIpEnd.Value; ipCount = end - start + 1; hasEndCount = 0; } } }
本文出自 “new妞宁” 博客,请务必保留此出处http://yang19890314.blog.51cto.com/1620466/1124828
相关文章推荐
- [深入学习C#]C#实现多线程的方法:线程(Thread类)和线程池(ThreadPool)
- C#网络程序设计1-3:线程支持
- C#初学者日记:多线程扫描网络计算机2
- c#初学日记:多线程扫描网络计算机
- C# 线程手册 第五章 扩展多线程应用程序 在C#中使用线程池
- C#网络程序设计1-5:方法回调、委托、线程的综合运用
- C#网络编程之单线程与多线程实例对比(3)
- C# 多线程学习(六)线程池(ThreadPool)——线程资源的复用和自动管理
- C# 多线程、异步线程、线程池相关知识
- C#制作Windows service 服务 实战 ip 地址的实时 扫描(网络跟踪的问题)
- c#网络编程之TCP/IP(一)C#线程任务基础Thread
- C# 线程手册 第五章 扩展多线程应用程序 - 什么是线程池
- [深入学习C#]C#实现多线程的方法:线程(Thread类)和线程池(ThreadPool)
- C# 多线程、异步线程、线程池相关知识
- C# 多线程、异步线程、线程池相关知识
- C# 多线程、异步线程、线程池相关知识
- 优雅设计封装基于Okhttp3的网络框架(三):多线程下载功能核心实现 及 线程池、队列机制、终止线程解析
- C#中的线程(三)多线程
- C#中的多线程与线程死锁
- C#如何判断线程池中所有的线程是否已经完成