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

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

作者:秋枫 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)

有一大串。

你可能感兴趣的:(thread,多线程,object,ListView,网络,String)