Sooo... I found an instance where the specified timeout with Ping.Send() or Ping.SendAsync do not adhere to the specified timeouts or TTLs and I am trying to work around it. When an invalid host is attempted to be pinged the specified timeout is ignored and in my case a full 2 seconds passes before the ping fails. For the project I am working on I need that to be something like 100 ms or less (if the host was valid it would only be a hop or 2 away so 100 ms seems plenty).
I've tried Ping.Send() and Ping.SendAsync and cannot for the life me figure out how to do this. The closest I got was doing a .Close on the AutoResetEvent but I couldn't catch/suppress the error that was created doing that. (Code not shown here)
Here is the current iteration of the code, as you can see I use both .Send and .SendAsync; I would prefer to use SendAsync I think... If you run the code below everything is executed in under 100ms (usually 60ms) for a host on the same network, but if the host in invalid the code doesn't exit till after 2000ms.
//.NETCore.App\3.1.4
// Microsoft Visual Studio Community 2019 - Version 16.5.5
// Microsoft Windows [Version 10.0.18362.836]
using System;
using System.Text;
using System.Net.NetworkInformation;
using System.Threading;
using System.Text.RegularExpressions;
class Program
{
public static void Main(string[] args)
{
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
string who = String.Empty;
//who = "firewall0"; //Hostname of my local firewall
//who = "www.yahoo.com";
who = "not-a-valid-host";
//who = "10.1.1.151"; //My interface
//who = "localhost"; //Should succeed but error has to be suppressed because of IPv6
//who = "2a03:2880:f131:83:face:b00c:0:25de"; //Facebook IPv6, should fail quickly
//who = "127.0.0.1";
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 1;
int numMaxHops = 1; //Supposedly this is TTL, but after some experimenting it appears to be number of hops not TTL in ms
Ping pingSender = new Ping();
PingOptions options = new PingOptions(numMaxHops, true);
if (true) //Use false to toggle off this section of code while testing
{
AutoResetEvent waiter = new AutoResetEvent(false);
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
Console.WriteLine("Time to live set to: {0}", options.Ttl);
Console.WriteLine("");
pingSender.SendAsync(who, timeout, buffer, options, waiter);
waiter.WaitOne();
Console.WriteLine("Ping example completed.");
}
if (true) //Use false to toggle off this section of code while testing
{
try
{
PingReply reply = pingSender.Send(who, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
if (reply.Address.ToString() != "::1")
{
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
}
}
else
{
Console.WriteLine(reply.Status);
}
}
catch (Exception ex)
{
Regex noHostMatch = new Regex("No such host is known");
if (noHostMatch.IsMatch(ex.InnerException.ToString()))
//if (false)
{
Console.WriteLine("No such host is known.");
}
else
{
throw;
}
}
}
watch.Stop();
Console.WriteLine("");
Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
Console.WriteLine("Press the Enter key");
Console.ReadLine();
}//End Main()
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
// Let the main thread resume.
// UserToken is the AutoResetEvent object that the main thread
// is waiting for.
((AutoResetEvent)e.UserState).Set();
}
// If an error occurred, display the exception to the user.
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
//Console.WriteLine(e.Error.ToString());
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
else
{
PingReply reply = e.Reply;
DisplayReply(reply);
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
}//End PingCompletedCallback()
public static void DisplayReply(PingReply reply)
{
if (reply == null)
return;
Console.WriteLine("Ping Status: {0}", reply.Status);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
if (reply.Address.ToString() != "::1")
{
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
}
}
}//End DisplayReply()
Out out from running the above while pinging my local firewall.
Time to live set to: 1
Ping Status: Success
Address: 10.1.1.1
RoundTrip time: 0
Time to live: 64
Don't fragment: False
Buffer size: 32
Ping example completed.
Address: 10.1.1.1
RoundTrip time: 0
Time to live: 64
Don't fragment: False
Buffer size: 32
Execution Time: 61 ms
Press the Enter key
Output when pinging not-a-valid-host
Time to live set to: 1
Ping failed:
Ping example completed.
No such host is known.
Execution Time: 2139 ms
Press the Enter key
^ I want to get that execution time down to under 100ms with an invalid host.
Put the ping call inside a Task and Wait() up to your chosen timeout, after that has completed or timed out, we check to see if reply was set.
I've implemented this into your code below
//.NETCore.App\3.1.4
// Microsoft Visual Studio Community 2019 - Version 16.5.5
// Microsoft Windows [Version 10.0.18362.836]
using System;
using System.Text;
using System.Net.NetworkInformation;
using System.Threading;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
class Program
{
public static void Main(string[] args)
{
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
string who = String.Empty;
//who = "firewall0"; //Hostname of my local firewall
//who = "www.yahoo.com";
who = "not-a-valid-host";
//who = "10.1.1.151"; //My interface
//who = "localhost"; //Should succeed but error has to be suppressed because of IPv6
//who = "2a03:2880:f131:83:face:b00c:0:25de"; //Facebook IPv6, should fail quickly
//who = "127.0.0.1";
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 1;
int numMaxHops = 1; //Supposedly this is TTL, but after some experimenting it appears to be number of hops not TTL in ms
Ping pingSender = new Ping();
PingOptions options = new PingOptions(numMaxHops, true);
if (false) //Use false to toggle off this section of code while testing
{
AutoResetEvent waiter = new AutoResetEvent(false);
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
Console.WriteLine("Time to live set to: {0}", options.Ttl);
Console.WriteLine("");
pingSender.SendAsync(who, timeout, buffer, options, waiter);
waiter.WaitOne();
Console.WriteLine("Ping example completed.");
}
if (true) //Use false to toggle off this section of code while testing
{
try
{
PingReply reply = null;
var t = Task.Run(() =>
{
reply = pingSender.Send(who, timeout, buffer, options);
Console.WriteLine("Ping example completed.");
});
t.Wait(TimeSpan.FromMilliseconds(100));
if (reply == null)
{
Console.WriteLine("timed out");
}
else if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
if (reply.Address.ToString() != "::1")
{
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
}
}
else
{
Console.WriteLine(reply.Status);
}
}
catch (Exception ex)
{
Regex noHostMatch = new Regex("No such host is known");
if (noHostMatch.IsMatch(ex.InnerException.ToString()))
//if (false)
{
Console.WriteLine("No such host is known.");
}
else
{
throw;
}
}
}
watch.Stop();
Console.WriteLine("");
Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
Console.WriteLine("Press the Enter key");
Console.ReadLine();
}//End Main()
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
// Let the main thread resume.
// UserToken is the AutoResetEvent object that the main thread
// is waiting for.
((AutoResetEvent)e.UserState).Set();
}
// If an error occurred, display the exception to the user.
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
//Console.WriteLine(e.Error.ToString());
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
else
{
PingReply reply = e.Reply;
DisplayReply(reply);
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
}//End PingCompletedCallback()
public static void DisplayReply(PingReply reply)
{
if (reply == null)
return;
Console.WriteLine("Ping Status: {0}", reply.Status);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
if (reply.Address.ToString() != "::1")
{
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
}
}
}//End DisplayReply()
}
Related
I have the following code that is working and pings all of the Runescape game servers and returns a list in the console of the ip addresses and the respective 'roundtrip' time taken.
EDIT 'IGNORE SOME OF THE OLD COMMENTS'
I am having trouble with the following:
A) How can I return the lowest ping out of all of the servers and write it to the console?
B) How can i return the original hostname or 'number' of the current 'server.ToString()' across methods?
public void buttonClick_Click(object sender, EventArgs e)
{
Console.WriteLine();
Ping();
}
public static void Ping()
{
for (int server = 1; server <= 110; server++)
{
string hostname = "oldschool" + server.ToString() + ".runescape.com";
// Get an object that will block the main thread.
AutoResetEvent waiter = new AutoResetEvent(false);
// Ping's the local machine.
Ping pingSender = new Ping();
// When the PingCompleted event is raised,
// the PingCompletedCallback method is called.
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
//Console.WriteLine("Send Before Async.");
// Send the ping asynchronously.
// Use the waiter as the user token.
// When the callback completes, it can wake up this thread.
pingSender.SendAsync(hostname, 1000, waiter);
//Console.WriteLine("Ping example completed.");
}
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
// Let the main thread resume.
// UserToken is the AutoResetEvent object that the main thread
// is waiting for.
((AutoResetEvent)e.UserState).Set();
}
// If an error occurred, display the exception to the user.
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
DisplayReply(reply);
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
public static void DisplayReply(PingReply reply)
{
List<long> lag = new List<long>();
if (reply == null)
return;
Console.WriteLine("Status: {0}", reply.Status);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("\r\n");
Console.WriteLine("Address: {0}", reply.Address);
Console.WriteLine("Ping: {0}", reply.RoundtripTime);
}
return;
}
I restructured your code so it should work. I also made pings run in parallel which should speed up results.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
namespace WindowsFormsApplication13
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
public class State
{
public string ip { get; set;}
public decimal roundTripTime { get; set; }
public IPStatus status { get;set;}
}
public class myPing
{
static const int NUMBER_SERVERS = 110;
public static List<State> states { get; set; }
public static int count = 0;
public myPing()
{
AutoResetEvent waiter = new AutoResetEvent(false);
for (int server = 1; server <= NUMBER_SERVERS; server++)
{
string hostname = "oldschool" + server.ToString() + ".runescape.com";
// Get an object that will block the main thread.
// Ping's the local machine.
Ping pingSender = new Ping();
// When the PingCompleted event is raised,
// the PingCompletedCallback method is called.
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
//Console.WriteLine("Send Before Async.");
// Send the ping asynchronously.
// Use the waiter as the user token.
// When the callback completes, it can wake up this thread.
pingSender.SendAsync(hostname, 1000, waiter);
//Console.WriteLine("Ping example completed.");
}
waiter.WaitOne();
DisplayReply(states);
Console.ReadLine();
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
// Let the main thread resume.
// UserToken is the AutoResetEvent object that the main thread
// is waiting for.
((AutoResetEvent)e.UserState).Set();
}
// If an error occurred, display the exception to the user.
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
State state = new State();
Object thisLock = new Object();
lock (thisLock)
{
states.Add(state);
}
state.ip = reply.Address.ToString();
state.roundTripTime = reply.RoundtripTime;
state.status = reply.Status;
count++;
// Let the main thread resume.
if (count == NUMBER_SERVERS)
{
((AutoResetEvent)e.UserState).Set();
}
}
public static void DisplayReply(List<State> replies)
{
foreach (State reply in replies)
{
Console.WriteLine("Status: {0}", reply.status);
if (reply.status == IPStatus.Success)
{
Console.WriteLine("\r\n");
Console.WriteLine("Address: {0}", reply.ip);
Console.WriteLine("Ping: {0}", reply.roundTripTime);
}
}
State shortest = replies.OrderBy(x => x.roundTripTime).FirstOrDefault();
Console.WriteLine("Shortest Route IP : '{0}' Time : '{1}'", shortest.ip.ToString(), shortest.roundTripTime.ToString() );
}
}
}
Debugging is being using Simple Web Socket Client.
So, my socket gets active on port X,
I successfully get the "Hello new client" message on Client.
When i send the first request/data to the server, server receives it and prints on console.
Post this, as soon as I send another request, session closed event is being triggered.
I checked Session's TimeOut: 60secs and KeepAliveTime: 600secs, which seem fine.
below is the code for SocketServer:
static void Main(string[] args)
{
Console.WriteLine("Press any key to start the server!");
Console.ReadKey();
Console.WriteLine();
var bootstrap = BootstrapFactory.CreateBootstrap();
if (!bootstrap.Initialize())
{
Console.WriteLine("Failed to initialize!");
Console.ReadKey();
return;
}
var result = bootstrap.Start();
Console.WriteLine("Start result: {0}!", result);
if (result == StartResult.Failed)
{
Console.WriteLine("Failed to start!");
Console.ReadKey();
return;
}
foreach (WebSocketServer appS in bootstrap.AppServers)
{
appS.NewDataReceived += new SessionHandler<WebSocketSession, byte[]>(appServer_NewDataReceived);
appS.NewSessionConnected += new SessionHandler<WebSocketSession>(appServer_NewSessionConnected);
appS.SessionClosed += new SessionHandler<WebSocketSession, CloseReason>(appServer_SessionClosed);
appS.NewMessageReceived += new SessionHandler<WebSocketSession, string>(appServer_NewMessageReceived);
}
Console.WriteLine("Press key 'q' to stop it!");
Char input;
while ((input = Console.ReadKey().KeyChar) != 'q')
{
Console.WriteLine();
continue;
}
Console.WriteLine();
//Stop the appServer
bootstrap.Stop();
Console.WriteLine();
Console.WriteLine("The server was stopped!");
Console.ReadKey();
}
private static void appServer_NewDataReceived(WebSocketSession session, byte[] message)
{
Console.WriteLine("Client said: " + message);
//Send the received message back
session.Send("Server responded back: " + message);
}
private static void appServer_NewSessionConnected(WebSocketSession session)
{
Console.WriteLine();
Console.WriteLine("New session connected! Sessions counter: " );
session.Send("Hello new client!");
}
private static void appServer_SessionClosed(WebSocketSession session, CloseReason value)
{
Console.WriteLine();
Console.WriteLine("Client disconnected! Sessions counter: ");
}
private static void appServer_NewMessageReceived(WebSocketSession session, string message)
{
Console.WriteLine("Client said: " + message);
//Send the received message back
session.Send("Server responded back: " + message);
}
Error on close is "Protocol Error"
I'm working on this program to ping a large number of IP Address simultaneously I tried simply pinging each address one at a time but Once I started pinging 50+ hosts it got insanely long. The problem I'm having is that I am unable to stop the asynchronous thread on the cancel button click and get this error when I try and ping more than 1 host. I've spent 2 days trying to get it figured out and had no luck. The exact error is as follows:
System.InvalidOperationException: An asynchronous call is already in
progress. It must be completed or canceled before you can call this method.
at System.Net.NetworkInformation.Ping.CheckStart(Boolean async)
at System.Net.NetworkInformation.Ping.Send(IPAddress address, Int32 timeout, Byte[] buffer, PingOptions options)
at MultiPing.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in f:\Dev\tfsMultiPing\Multi Ping\MultiPing\MultiPing\Form1.cs:line 139
private void pingBtn_Click(object sender, EventArgs e)
{
try
{
if (inputBox.Text == "")
{
MessageBox.Show("Please Enter an IP Address to Ping.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
if (backgroundWorker1.IsBusy != true)
{
backgroundWorker1.RunWorkerAsync();
}
else
{
MessageBox.Show("Please Cancel current Ping or wait for it to be completed");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
try
{
this.Invoke(new MethodInvoker(delegate { progressBar1.Enabled = true; }));
int i;
//Add each line in the input box to the "allLines" string array
string[] allLines = inputBox.Lines;
Ping pingSender = new Ping();
try
{
//Get an object that will block the main thread
AutoResetEvent waiter = new AutoResetEvent(false);
//When the PingCompleted even is raised,
//The PingCompletedCallback method is called.
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
//Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
//Wait 2 seconds for a reply.
int timeout = 2000;
//Set Options for transmission:
//The data can go through 64 gateways or routers
//before it is destroyed, and the data packet
//cannot be fragmented
PingOptions options = new PingOptions(64, true);
//Check if Cancel Button was clicked
if (backgroundWorker1.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
//Begin Loop to ping each given IP Address
for (i = 0; i < allLines.Length; i++)
{
//Check if Cancel Button was clicked
if (backgroundWorker1.CancellationPending == true)
{
e.Cancel = true;
return;
}
else
{
//Convert each line from the input box to an IP address
IPAddress address = IPAddress.Parse(allLines[i]);
//Send ping Asynchronously
//Use the waiter as the user token.
//When the callback complets, it can wake up this thread.
pingSender.SendAsync(address, timeout, buffer, options, waiter);
PingReply reply = pingSender.Send(address, timeout, buffer, options);
waiter.WaitOne();
//If a replay is recieved Print "IP Address" is up in the output box.
if (reply.Status == IPStatus.Success)
{
this.Invoke(new MethodInvoker(delegate { outputBoxLive.AppendText(address + " is up" + Environment.NewLine); }));
}
//If no reply is recieved then print "IP Address" is down in the output box.
else if (reply.Status == IPStatus.TimedOut)
{
this.Invoke(new MethodInvoker(delegate { outputBoxDown.AppendText(address + " is down" + Environment.NewLine); }));
pingSender.Dispose();
}
pingSender.Dispose();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void pingStuff()
{
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
//If the operation was cancelled, Display a message to the user
if (e.Cancelled)
{
MessageBox.Show("Ping Cancelled");
//Let the main thread resume.
//User token is the AutoResetEvent object that the main thread is waiting for
((AutoResetEvent)e.UserState).Set();
}
//If an error occurred, Display the exception to the user.
if (e.Error != null)
{
MessageBox.Show("Ping Failed: " + e.Error.ToString());
//Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
DisplayReply(reply);
//Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
public static void DisplayReply(PingReply reply)
{
if (reply == null)
return;
Console.WriteLine("ping status: [0]", reply.Status);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
}
}
public void button2_Click(object sender, EventArgs e)
{
try
{
backgroundWorker1.CancelAsync();
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
}
}
}
The immediate issue with your code (i.e. the cause of the exception) is that you are calling both Ping.Send() and Ping.SendAsync() in your loop. Once you have called Ping.SendAsync(), any subsequent call to Send() or SendAsync() is illegal until the first SendAsync() operation has completed.
It's not clear why you even have both. Given that you appear to want to make the call synchronously, the simplest thing is to simply remove the call to SendAsync() and anything related to it (i.e. the waiter object). Alternatively, since you seem to want to be able to interrupt the operation, you may prefer to remove the call to Send(), so that you can use the SendAsyncCancel() method to interrupt an outstanding operation.
Lacking a good, complete code example (this code example doesn't show the full context, including where you get the addresses to ping), it's hard to know exactly what is wrong in your scenario. But I can offer a couple of observations about the code you did post:
You are calling the Ping.Dispose() method in each iteration of your loop. This means only in the first iteration of the loop should you expect to succeed. In the next iteration, you should be getting an ObjectDisposedException, terminating the work!
If you want to cancel an in-progress call to Ping.SendAsync(), you should call the Ping.SendAsyncCancel() method. This will cause the current ping operation to complete with cancellation status. Of course, to do this you will need to expose the pingSender reference to the form's code somehow, so that the button2_Click() method has access to it.
I am using the following to ping a host name:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = pingData;
p.Start();
p.WaitForExit();
string result = p.StandardOutput.ReadToEnd();
System.Windows.Forms.Clipboard.SetText(result);
if(p.HasExited)
{
richTextBox1.Text = result;
outPut = result;
MessageBox.Show( "Ping request has completed. \n Results have been copied to the clipboard.");
}
Is there anyway I can have a progress bar "load" during the ping command and complete the loading when the ping has completed?
Thank you.
http://msdn.microsoft.com/en-us/library/system.net.networkinformation.pingcompletedeventhandler(v=vs.110).aspx even has an example of how to use Ping. Depending on how you want to display the progress bar, you could modify the example to have the event handler set a flag indicating that the ping has completed. Then add a while loop in the main execution thread that fills in the progress bar as a percent of the elapsed time / timeout value. Below is the example reformatted as an example
namespace PingTest
{
using global::System;
using System.Diagnostics;
using global::System.Net.NetworkInformation;
using System.Text;
using System.Threading;
/// <summary>
/// The ping example.
/// </summary>
public class PingExample
{
#region Static Fields
private static bool pingComplete;
#endregion
#region Public Methods and Operators
public static void DisplayReply(PingReply reply)
{
if (reply == null)
{
return;
}
Console.WriteLine("ping status: {0}", reply.Status);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address);
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
}
}
public static void Main(string[] args)
{
if (args.Length == 0)
{
throw new ArgumentException("Ping needs a host or IP Address.");
}
string who = args[0];
var waiter = new AutoResetEvent(false);
var pingSender = new Ping();
// When the PingCompleted event is raised,
// the PingCompletedCallback method is called.
pingSender.PingCompleted += PingCompletedCallback;
// Create a buffer of 32 bytes of data to be transmitted.
const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(Data);
// Wait 12 seconds for a reply.
const int Timeout = 12000;
// Set options for transmission:
// The data can go through 64 gateways or routers
// before it is destroyed, and the data packet
// cannot be fragmented.
var options = new PingOptions(64, true);
Console.WriteLine("Time to live: {0}", options.Ttl);
Console.WriteLine("Don't fragment: {0}", options.DontFragment);
// Send the ping asynchronously.
// Use the waiter as the user token.
// When the callback completes, it can wake up this thread.
pingComplete = false;
var watch = Stopwatch.StartNew();
watch.Start();
pingSender.SendAsync(who, Timeout, buffer, options, waiter);
while (!pingComplete && watch.ElapsedMilliseconds <= Timeout)
{
// Do display stuff for your progress bar here.
}
// Prevent this example application from ending.
// A real application should do something useful
// when possible.
waiter.WaitOne();
Console.WriteLine("Ping example completed.");
Console.ReadLine();
}
#endregion
#region Methods
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
// Let the main thread resume.
// UserToken is the AutoResetEvent object that the main thread
// is waiting for.
((AutoResetEvent)e.UserState).Set();
}
// If an error occurred, display the exception to the user.
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
pingComplete = true;
DisplayReply(reply);
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
#endregion
}
}
How to scan a specific range of IP and also increment it to user defined range.. in like most of the port scanners. but how to increase host bits.. it increases network bits..
private static void sendAsyncPingPacket(string hostToPing)
{
try
{
int timeout = 5000;
AutoResetEvent waiter = new AutoResetEvent(false);
Ping pingPacket = new Ping();
//ping completion event reaised
pingPacket.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
string data = "Ping test check";
byte[] byteBuffer = Encoding.ASCII.GetBytes(data);
PingOptions pingOptions = new PingOptions(64, true);
Console.WriteLine("Time to live: {0}", pingOptions.Ttl);
//Console.WriteLine("Don't fragment: {0}", pingOptions.DontFragment);
pingPacket.SendAsync(hostToPing, timeout, byteBuffer, pingOptions, waiter);
//do something useful
waiter.WaitOne();
Console.WriteLine("Ping RoundTrip returned, Do something useful here...");
}
catch (PingException pe)
{
Console.WriteLine("INVALID IP ADDRESS FOUND");
}
catch (Exception ex)
{
Console.WriteLine("Exceptin " + ex.Message);
}
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
try
{
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
// Let the main thread resume.
// UserToken is the AutoResetEvent object that the main thread
// is waiting for.
((AutoResetEvent)e.UserState).Set();
}
// If an error occurred, display the exception to the user.
if (e.Error != null)
{
Console.WriteLine("Ping failed>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ");
//this will print exception
//Console.WriteLine (e.Error.ToString ());
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
DisplayReply(reply);
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
catch (PingException pe)
{
Console.WriteLine("INVALID IP ADDRESS");
}
catch (Exception ex)
{
Console.WriteLine("Exception " + ex.Message);
}
}
public static void DisplayReply (PingReply reply)
{
if (reply == null)
return;
Console.WriteLine ("ping status: {0}", reply.Status);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine ("Address: {0}", reply.Address.ToString ());
Console.WriteLine ("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine ("Time to live: {0}", reply.Options.Ttl);
//Console.WriteLine ("Don't fragment: {0}", reply.Options.DontFragment);
Console.WriteLine ("Buffer size: {0}", reply.Buffer.Length);
}
}
private static long ToInt(string addr)
{
return (long)(uint)System.Net.IPAddress.NetworkToHostOrder(
(int)System.Net.IPAddress.Parse(addr).Address);
}
private static string ToAddr(long address)
{
return System.Net.IPAddress.Parse(address.ToString()).ToString();
}
static int temp = 0;
private static void scanLiveHosts(string ipFrom, string ipTo)
{
long from = Program.ToInt(ipFrom);
long to = Program.ToInt(ipTo);
long ipLong = Program.ToInt(ipFrom);
while ( from < to)
{
string address = Program.ToAddr(ipLong);
Program.sendAsyncPingPacket(address);
ipLong++;
}
}
static void Main(string[] args)
{
try
{
Program.getDeviceList();
Program.sendAsyncPingPacket("192.168.3.72");
Program.scanLiveHosts("192.168.3.1", "192.168.3.41");
}
catch (InvalidOperationException ioe)
{
Console.WriteLine(ioe.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Main Methods used are
private static long ToInt(string addr)
{
return (long)(uint)System.Net.IPAddress.NetworkToHostOrder(
(int)System.Net.IPAddress.Parse(addr).Address);
}
private static string ToAddr(long address)
{
return System.Net.IPAddress.Parse(address.ToString()).ToString();
}
above post is in depth how to send ping packet and scan network.
Hey i found the code by google, i've make little changes to fit my code and other changes to fit your code... maybe you should think about change:
while ( from < to)
{
string address = Program.ToAddr(ipLong);
Program.sendAsyncPingPacket(address);
ipLong++;
}
to something like:
while ( ipLong < to)
{
string address = Program.ToAddr(ipLong);
Program.sendAsyncPingPacket(address);
ipLong++;
}
or the "quest" for ips will not stop at ToAddr(to)