现在的位置: 首页 > 综合 > 正文

编写多线程网络检测程序的简单实现

2013年08月14日 ⁄ 综合 ⁄ 共 6915字 ⁄ 字号 评论关闭

编写多线程网络检测程序的简单实现

作者:秋枫
2004-7-8

        
前段时间编写过一个简单的网络连接检测程序,功能就是检测某一个网段中的计算机跟本机的连接情况。小程序自己用用感觉还行,不过写的比较简单,没有什么特殊的功能也就没有放到BLOG上。最近看到CSDN论坛中有网友提及这方面的问题,所以把程序搬了出来,望能给那些需要的网友带来些许帮助。

程序的整个界面如下:

 

备注:

TextBox:用来输入一个C类的网段;

NumericUpDown:用来选择网段内的IP范围;

NumericUpDown3:用来选择一个线程最多处理的IP数量。

整个程序的一个主要类就是PingCommand类,如果要采用套接字实现可以参考孟子e一篇文章

using System;

using System.Diagnostics;

 

namespace ZZ

{

    
///

    
/// PingCompleted
事件委托

    
///

    
public delegate
void PingCompletedHandler(object sender,PingEventArgs e);

    
///

    
/// PingCommand
的摘要说明。

    
///

    
public class PingCommand

    
{

        
///

        
/// PingCompleted
事件

        
///

        
public event PingCompletedHandler PingCompleted;

        
private string [] _ips;

        
private Process _p;

        
///

        
///
构造函数

        
///

        
///

        
public PingCommand(string [] ips)

        
{

             
this._ips = ips;

             
this._p = new Process();

             
this._p.StartInfo.UseShellExecute =
false
;

             
this._p.StartInfo.RedirectStandardInput =
true
;

             
this._p.StartInfo.RedirectStandardOutput =
true;

             
this._p.StartInfo.RedirectStandardError =
true
;

             
this._p.StartInfo.CreateNoWindow =
true
;

             
this._p.StartInfo.FileName = "cmd.exe";

        
}

        
///

        
///
线程调用方法

        
///

        
public void RunPings()

        
{

             
Ping(this._ips);

        
}

        
///

        
///
执行ping命令

        
///

        
///

        
public void Ping(string ip)

        
{

             
_p.Start();

             
_p.StandardInput.WriteLine("ping -n 1 "+ip);

        
     _p.StandardInput.WriteLine("exit");

             
string strRst = _p.StandardOutput.ReadToEnd();

             
_p.Close();

             
if(strRst.IndexOf("(0% loss)")!=-1)

                  
strRst = "
连接";

             
else if(strRst.IndexOf("Request timed out.")!=-1)

                  
strRst = "
超时";

             
else if(strRst.IndexOf("Destination host unreachable.")!=-1)

                  
strRst = "
无法到达目的主机";

             
else if(strRst.IndexOf("Unknown host")!=-1)

                  
strRst = "
无法解析主机";

             
OnPingCompleted(this,new PingEventArgs(new
string [,]{{ip,strRst}}));

        
}

        
///

        
///
事件处理

        
///

        
///

        
///

        
protected virtual
void OnPingCompleted(object sender,PingEventArgs e)

        
{

             
if(PingCompleted !=
null
)

                  
PingCompleted(sender,e);

        
}

        
///

        
///
执行ping命令

        
///

        
///

        
public void Ping(string [] ips)

        
{

             
foreach(string ip
in ips)

                  
Ping(ip);

        
}

    
}

    
///

    
///
定义参数类

    
///

    
public class PingEventArgs : EventArgs

    
{

        
private string [,] _pingResult;

        
///

        
///
构造函数

        
///

        
/// Ping
结果

        
public PingEventArgs(string [,] pingResult)

        
{

             
this._pingResult = pingResult;

        
}

        
///

        
/// Ping
结果

        
///

        
public string[,] PingResult

        
{

             
get{return
this._pingResult;}

        
}

 

    
}

}

上面PingEventArgs类为EventArgs的继承类,用来传递执行Ping命令的结果。还有上面public
void Ping(string ip)
方法里面的判断不是完全的,调用的shell命令为“ping
 -n 1 ipaddress
”,具体可以参考相关文章,这里有一个需要注意的是定义了一个Process类成员变量,在构造函数中进行实例化然后就是重复使用,如果是在每次调用Ping方法时都实例化一个Process类就会变得很慢。

另一个就是窗体类了,里面用一个ArrayList来保存线程对象,下面是主要代码:

 

namespace ZZ

{

    
public class FormMain : System.Windows.Forms.Form

    
{

        
//
委托

        
private delegate
void UpdateListViewHandler(string[,] pingResult);

        
private ArrayList ThreadArray;//
用来保存线程

        
private DateTime startTime;//
检测起始时间

        
private int hostCount;//IP
数量

……

//构造函数

public FormMain()

{

    
         InitializeComponent();

             
this.labelLocal.Text = "
本地主机:"+Environment.MachineName;

             
this.ThreadArray =
new
ArrayList();

        
}

        
///
运行按钮执行函数,用来启动网络检测

        
private void buttonPing_Click(object sender, System.EventArgs e)

        
{

             
this.listView1.Items.Clear();

             
this.labelTime.Text = String.Empty;

             
int start = (int)this.numericUpDownStart.Value;

             
int end = (int)this.numericUpDownEnd.Value;

             
this.hostCount = end-start+1;

             
string cAddress =
this
.textBox1.Text.Substring(0,this.textBox1.Text.LastIndexOf("."));

             
ArrayList ipsList = new ArrayList();

             
for(int i=start;i<=end;i++)

             
{

                  
ipsList.Add( String.Format(cAddress+".{0}",i));

             
}

             
string [] ips = (string[])ipsList.ToArray(typeof(string));

 

             
if(ips != null && ips.Length>0)

             
{

                  
this.buttonPing.Enabled =
false
;

                  
this.startTime = DateTime.Now;

                  

                  
int arrayLenth = (int)this.numericUpDownMax.Value;//
一个线程执行的IP

                  
int threadCount = (int)Math.Floor(ips.Length/arrayLenth);//
计算线程的数量,如果为0,计算余数

                  
this.ThreadArray.Clear();

                  
Thread PingThread = null;

                  
string[] newIps =
null
;

                  
for(int i=0;i<threadCount;i++)

                  
{

                      
newIps = new string[arrayLenth];

                      
Array.Copy(ips,i*arrayLenth,newIps,0,arrayLenth);

 

                      
PingCommand pingCommand = new PingCommand(newIps);

                      
PingThread = new Thread(new ThreadStart(pingCommand.RunPings));

                      
pingCommand.PingCompleted += new PingCompletedHandler(pingCommand_PingCompleted);

                      
this.ThreadArray.Add(PingThread);

                      
PingThread.Start();

                  
}

                  
int endCount = (ips.Length%arrayLenth);//
计算余数

                  
if(endCount>0)

                  
{

                      
newIps = new string[endCount];

                      
Array.Copy(ips,ips.Length-endCount-1,newIps,0,endCount);

    
                   PingCommand pingCommand =
new
PingCommand(newIps);

                      
PingThread = new Thread(new ThreadStart(pingCommand.RunPings));

                      
pingCommand.PingCompleted +=new PingCompletedHandler(pingCommand_PingCompleted);

                      
this.ThreadArray.Add(PingThread);

                      
PingThread.Start();

                  
}

                  
this.labelThreadCount.Text = "
线程数:"+this.ThreadArray.Count.ToString();

             
}

        
}

        
//
更新信息显示,Invoke异步调用

        
private void pingCommand_PingCompleted(object sender,PingEventArgs e)

        
{

             
this.listView1.BeginInvoke(new UpdateListViewHandler(MessageInfoShow),new
object[]{e.PingResult});

        
}

        
//
更新ListView

        
private void MessageInfoShow(string[,] pingResult)

        
{

             
this.listView1.Items.Insert(0,new ListViewItem(new
string []{pingResult[0,0],pingResult[0,1]}));

             
if(this.listView1.Items.Count ==this.hostCount)

             
{

                  
this.listView1.Refresh();

                  
TimeSpan ts = (TimeSpan)(DateTime.Now-this.startTime);

                  
this.labelTime.Text = "
检测时间:"+ts.TotalSeconds.ToString()+"";

                  
this.buttonPing.Enabled =
true
;

             
}

        
}

                  
//退出程序

        
private void buttonExit_Click(object sender, System.EventArgs e)

        
{

             
Application.Exit();

        
}

    
}

}//命名空间

 

这里看了线程执行完后的输出信息

线程 '<无名称>' (0x1538)
已退出,返回值为 0 (0x0)

有一大串。

抱歉!评论已关闭.