我目前有代码获取一系列IP地址(例如192.168.1.101到192.168.1.110)并使用for循环单独ping它们。问题是这需要太长时间,特别是如果ping不成功。同时ping 10个ip地址是个好主意吗?我尝试使用后台工作者,我在使用多个后台工作者时犹豫不决。 这是我的工作代码:
private void btnPingRange_Click(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
backgroundWorker1.RunWorkerAsync();
UpdateControls(true);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
UpdateControls(false);
}
static uint str2ip(string ip)
{
string[] octets = ip.Split('.');
uint x1 = (uint)(Convert.ToByte(octets[0]) << 24);
uint x2 = (uint)(Convert.ToByte(octets[1]) << 16);
uint x3 = (uint)(Convert.ToByte(octets[2]) << 8);
uint x4 = (uint)(Convert.ToByte(octets[3]));
return x1 + x2 + x3 + x4;
}
static string ip2str(uint ip)
{
string s1 = ((ip & 0xff000000) >> 24).ToString() + ".";
string s2 = ((ip & 0x00ff0000) >> 16).ToString() + ".";
string s3 = ((ip & 0x0000ff00) >> 8).ToString() + ".";
string s4 = (ip & 0x000000ff).ToString();
string ip2 = s1 + s2 + s3 + s4;
return ip2;
}
public string GetMacAddress(string ipAddress)
{
string macAddress = string.Empty;
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
pProcess.StartInfo.FileName = "arp";
pProcess.StartInfo.Arguments = "-a " + ipAddress;
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.CreateNoWindow = true;
pProcess.Start();
string strOutput = pProcess.StandardOutput.ReadToEnd();
string[] substrings = strOutput.Split('-');
if (substrings.Length >= 8)
{
macAddress = substrings[3].Substring(Math.Max(0, substrings[3].Length - 2))
+ "-" + substrings[4] + "-" + substrings[5] + "-" + substrings[6]
+ "-" + substrings[7] + "-"
+ substrings[8].Substring(0, 2);
return macAddress;
}
else
{
return "not found";
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
uint startIP = str2ip(txtFrom.Text);
uint endIP = str2ip(txtTo.Text);
DataTable pingResults = new DataTable();
pingResults.Columns.Add("Date");
pingResults.Columns.Add("IP Address");
pingResults.Columns.Add("Mac Address");
pingResults.Columns.Add("Result");
//slow part
for (uint currentIP = startIP; currentIP <= endIP; currentIP++)
{
string thisIP = ip2str(currentIP);
Ping ping = new Ping();
PingReply pingReply = ping.Send(thisIP.ToString());
var message = (pingReply.Status == IPStatus.Success) ? "On" : "Off";
pingResults.Rows.Add(DateTime.Now.ToShortDateString(), thisIP.ToString(),GetMacAddress(thisIP), message.ToString());
}
dataGridView1.DataSource = pingResults;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void UpdateControls(bool isVisible)
{
if (isVisible)
{
panel1.Visible = true;
pictureBox1.Refresh();
pictureBox2.Refresh();
groupBox1.Enabled = false;
groupBox2.Enabled = false;
}
else
{
panel1.Visible = false;
groupBox1.Enabled = true;
groupBox2.Enabled = true;
}
}
答案 0 :(得分:1)
这是不可能的。您每次只能ping一个IP。在CMD中也是如此。您无法ping 127.0.0.1 127.0.0.2或使用,。
一个好主意是 - 正如一些人在评论中建议的那样 - 使用线程。在1 ping&#39;命令中没有办法ping多个IP。
答案 1 :(得分:1)
我运行一个程序,通过线程ping网络中的15000台机器。 有趣的是,我几乎看不到任何网络流量,尽管它每秒ping /检查200个系统。
小心! DataTable不是线程安全的。我写了一个单独的方法来锁定每次更新的DataTable。
public static void UpdateValue(DataRow dr, string property, object value)
{
Monitor.Enter(computerTable);
try
{
dr[property] = value;
}
catch
{
//Do something with errors
}
finally
{
Monitor.Exit(computerTable);
}
}
系统本身将决定它应该启动多少背景工作者。它会立即对所有这些进行排队,然后根据系统性能开始处理它们。
答案 2 :(得分:0)
对于遇到同样问题的所有人,我编写了这个(我使用了Parallel.For循环):
static uint str2ip(string ip)
{
//this converts the ip address from the textboxes to bytes
string[] octets = ip.Split('.');
uint x1 = (uint)(Convert.ToByte(octets[0]) << 24);
uint x2 = (uint)(Convert.ToByte(octets[1]) << 16);
uint x3 = (uint)(Convert.ToByte(octets[2]) << 8);
uint x4 = (uint)(Convert.ToByte(octets[3]));
return x1 + x2 + x3 + x4;
}
private volatile DataTable pingResults = new DataTable();
//And I use str2ip in the button click event which contains this:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
pingResults.Clear();
uint startIP = str2ip(txtFrom.Text);
uint endIP = str2ip(txtTo.Text);
Parallel.For(startIP, endIP, index => pingIpAddress(ip2str(startIP++)));
Thread.Sleep(1000);
//for (uint currentIP = startIP; currentIP <= endIP; currentIP++)
// {
// string thisIP = ip2str(currentIP);
// Thread myNewThread = new Thread(() => pingIpAddress(thisIP));
// myNewThread.Start();
// }
dataGridView1.DataSource = pingResults;
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Exception {0} Trace {1}", ex.Message, ex.StackTrace));
}
}
private void pingIpAddress(string ip3)
{//this method is where I ping the IP addresses
try
{
string ip2 = ip3;
Ping ping = new Ping();
PingReply pingReply = ping.Send(ip2.ToString());
var message = (pingReply.Status == IPStatus.Success) ? "On" : "Off";
lock (pingResults.Rows.SyncRoot)
{
AddToDataTable(ip2, message);
}
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Exception {0} Trace {1}", ex.Message, ex.StackTrace));
}
}
private void AddToDataTable(string ip2,string msg)
{
try
{
pingResults.Rows.Add(DateTime.Now.ToShortDateString(), ip2, GetMacAddress(ip2), msg.ToString(), GetMachineNameFromIPAddress(ip2));
}
catch (Exception)
{
throw;
}
}