I'm trying to get the list of all hosts on my local network. Following this Stackoverflow thread. But Ping.SendAsync() is stuck in infinite loop even if I keep a very little timeout i.e., 20. Here is my code.
static CountdownEvent countdown;
static int upCount = 0;
static object lockObj = new object();
const bool resolveNames = false;
static List<string> activeInterfaces = new List<string>();
static void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
try
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
//if (resolveNames)
//{
// string name;
// try
// {
// IPHostEntry hostEntry = Dns.GetHostEntry(ip);
// name = hostEntry.HostName;
// }
// catch (SocketException ex)
// {
// name = "?";
// }
// Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
//}
//else
//{
activeInterfaces.Add(ip);
Console.WriteLine("{0} is up: ({1} ms)", ip, e.Reply.RoundtripTime);
//}
lock (lockObj)
{
upCount++;
}
}
else if (e.Reply == null)
{
Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
}
countdown.Signal();
}
catch (Exception exp)
{
Console.WriteLine("Here you go...");
}
}
[HttpGet]
[Route("api/pc/getOnlinePCs")]
public List<string> GetOnlinePCs()
{
activeInterfaces.Clear();
//List<string> activeInterfaces=new List<string>();
string ipBase = "";
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
ipBase = ip.ToString().Substring(0, (ip.ToString().LastIndexOf(".") + 1));//"10.22.4.";
}
}
countdown = new CountdownEvent(1);
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 2; i < 254; i++)
{
string ip = ipBase + i.ToString();
//var tcpClient = new TcpClient();
//tcpClient.Connected += new PingCompletedEventHandler(p_PingCompleted);
Ping ping = new Ping();
ping.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
countdown.AddCount();
ping.SendAsync(ip, 20, ip);
}
countdown.Signal();
countdown.Wait();
sw.Stop();
TimeSpan span = new TimeSpan(sw.ElapsedTicks);
Console.WriteLine("Took {0} milliseconds. {1} hosts active.", sw.ElapsedMilliseconds, upCount);
Console.ReadLine();
return activeInterfaces;
}
I don't think the solution provided in SO thread is expired, rather I would be making a small logical mistake as I'm a front-end guy. Thanks!
Edit
As per an expert comment, I wrapped the SendAsync code in try/catch and finally block as
try
{
Ping ping = new Ping();
ping.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
countdown.AddCount();
ping.SendAsync(ip, 20, ip);
}
catch(Exception exception)
{
Console.WriteLine($"Exception on {ip} .Technical details: {exception}");
}
finally
{
countdown.AddCount();
}
But when I debug the code it always fall to finally block. Not to exception block and after the 253 pings iteration completed, again infinite loop! @Evk and @jdweng Please Help!