Making a "ping" inside of my C# application - c#

I need my application to ping an address I'll specify later on and just simply copy the Average Ping Time to a .Text of a Label.
Any help?
EDIT:
I found the solution in case anyone is interested:
Ping pingClass = new Ping();
PingReply pingReply = pingClass.Send("logon.chronic-domination.com");
label4.Text = (pingReply.RoundtripTime.ToString() + "ms");

Give a look the NetworkInformation.Ping class.
An example:
Usage:
PingTimeAverage("stackoverflow.com", 4);
Implementation:
public static double PingTimeAverage(string host, int echoNum)
{
long totalTime = 0;
int timeout = 120;
Ping pingSender = new Ping ();
for (int i = 0; i < echoNum; i++)
{
PingReply reply = pingSender.Send (host, timeout);
if (reply.Status == IPStatus.Success)
{
totalTime += reply.RoundtripTime;
}
}
return totalTime / echoNum;
}

Just as a sidenote to this. There is allready a project on sourceforge doing about that what you want. This has also included an implementation of ICMP (RFC 792)
Sourceforge Project

Related

Why pingsender.Send Method causing problem in code and how to reduce IP scanning time using this function?

for (int i = 5; i <= 15; i++)
{
string temp = string.Concat(base_IP, i.ToString());
//await Task.Delay(1000);
PingReply reply = pingsender.Send(temp, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
textbox_progress.Text = textbox_progress.Text + "Connected IP -> " + temp + "\n\r";
}
progressBar.Value++;
}
textbox_progress.Text = textbox_progress.Text + "Scanning Complete " + "\n\r";
In the code segment , the progress-bar should increment with the increase in the value of variable 'i'. However , it doesn't happen. The progress-bar get's updated all at once after the loop ends. If I comment out the IP scanning function and use the delay function, the progress-bar works properly. Can anyone help me to fix it?
Besides this, the scanning time is too long. I simply transmitted "abcd" to get ping. This small loop takes approximately 6 seconds to complete. The value of "timeout" is one [Although I'm confused if the "pingsender.Send()" function takes it as seconds or milliseconds]. I
The ProgressBar cannot be updated while your for loop is being executed on the same thread. This is impossible.
Use the asynchronous SendPingAsync method:
for (int i = 5; i <= 15; i++)
{
string temp = string.Concat(base_IP, i.ToString());
PingReply reply = await pingsender.SendPingAsync(temp, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
textbox_progress.Text = textbox_progress.Text + "Connected IP -> " + temp + "\n\r";
}
progressBar.Value++;
}
textbox_progress.Text = textbox_progress.Text + "Scanning Complete " + "\n\r";
Although I'm confused if the "pingsender.Send()" function takes it as seconds or milliseconds
The timeout parameter specifies the maximum number of milliseconds (after sending the echo message) to wait for the ICMP echo reply message.

An alternative class for Tracert with DNS feature

I noticed, using Tracert on Windows, that if there is no data for DNS info, there is a delay too long to be acceptable - more or less 5 seconds. For this reason, I coded my own Tracert class with a latency parameter, waiting for an answer. All is done using a Task method. However, if I code for a few years, now I am trying to elaborate my code cleanly and efficiently. Please, can you tell me what I should change? Maybe you see some mistakes or non-senses. Thank you for your help ++
enter image description here
class TraceRoute
{
public void TraceRouteX(string ipAddressOrHostName, int hops = 30, int latency = 1000, bool dns = false)
{ // this way we can check if IP or HostName are valid
try
{ // a tip to get only IPv4
IPAddress ipAddress = Dns.GetHostAddresses(ipAddressOrHostName).First(address => address.AddressFamily == AddressFamily.InterNetwork);
using (Ping pingSender = new Ping())
{
PingOptions pingOptions = new PingOptions();
Stopwatch stopWatch = new Stopwatch();
byte[] bytes = new byte[32]; // 32 bits as packet
string hostName; // for DNS
PingReply pingReply;
pingOptions.DontFragment = true;
pingOptions.Ttl = 1;
int maxHops = hops;
// just a first message on screen before TraceRoute
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(string.Format(" TraceRoute to {0} with a maximum of {1} hops, setting latency to {2} and DNS feature to {3}\n", ipAddress, maxHops, latency, dns));
Console.ResetColor();
for (int i = 1; i < maxHops + 1; i++)
{ // for latence
stopWatch.Reset();
stopWatch.Start(); // ping options allows us to set TTL
pingReply = pingSender.Send(ipAddress, latency, new byte[32], pingOptions);
stopWatch.Stop();
if (dns)
{ // DNS resolving using a timer
Task<string> task = Task<string>.Factory.StartNew(() =>
{
var t = Dns.GetHostEntry(pingReply.Address).HostName;
return t.ToString(); // well well ?
});
// waiting an answer
bool success = task.Wait(latency);
if (success)
hostName = task.Result;
else
hostName = "TimeOut (no DNS info)";
}
else
hostName = "";
// display string with all informations - easy reading
if (i % 2 == 0)
Console.ForegroundColor = ConsoleColor.DarkYellow;
else
Console.ForegroundColor = ConsoleColor.Cyan;
// display final output
Console.WriteLine(string.Format(" h{0}\t{1} ms\t{2}\t\t{3}", i, stopWatch.ElapsedMilliseconds, pingReply.Address, hostName));
Console.ResetColor();
// status
if (pingReply.Status == IPStatus.Success)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("\n The IP target " + pingReply.Address + " has been reached");
Console.ResetColor();
break;
}
// increment TTL to get the next node
pingOptions.Ttl++;
}
}
}
catch
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(" ERROR: You Have Some TIMEOUT Issue Or An Invalid IP/Host");
Console.ResetColor();
}
}
}

Response cut while reading System.Net.Sockets

I have this code inside of a controller that is called from a view by multiple users. The purpose is to read data from a socket while the socket has information to deliver. Multiple calls can happen simultaneously. The problem is, for a same call the Socket will sometimes cut the message. We will not read it entirely. Is there something wrong in my call that could lead to an incomplete reading of the Socket ? I am not able to reproduce it on my dev environment I just know that on the production we have responses from the Socket being randomly cut / incomplete.
int byteCount = 1;
string response = "";
int total = 0;
bytesReceived = new Byte[8000];
bool bytesAreAvailable = true;
while (byteCount > 0 || bytesAreAvailable)
{
try {
byteCount = m_oSocket.Receive(bytesReceived, bytesReceived.Length, 0);
total += byteCount;
Debug.WriteLine("Bytecount: " + byteCount.ToString());
Debug.WriteLine("Avalable: " + m_oSocket.Available.ToString());
if (m_oSocket.Available > 0)
bytesAreAvailable = true;
else
bytesAreAvailable = false; //Everything was read
response += Encoding.UTF8.GetString(bytesReceived, 0, byteCount);
}
catch(Exception e)
{
Debug.WriteLine(e.Message);
}
}
Debug.WriteLine(response.ToString());
Thanks a lot for any help / tips you could have on solving my issue

How to make run real time and faster refresh method with timer

I have script for refresh network with object label and panel but in script using looping mode with 'for'. I want to this real time refresh for 1 sec or 5 sec but because using 'for' make this procces need more time and get stuck screen. how to make the solution more quickly and in real time?
Thanks
public PosPing()
{
InitializeComponent();
RefreshPOS.Tick += new EventHandler(CheckPOSUG);
RefreshPOS.Start();
}
private void CheckPOSUG(object sender, EventArgs e)
{
Panel[] panelUG = new Panel[]{pnlPOSUG1,pnlPOSUG2,pnlPOSUG3,pnlPOSUG4,pnlPOSUG5,pnlPOSUG6,pnlPOSUG7,pnlPOSUG8};
Label[] LabelUG = new Label[]{lblUG1,lblUG2,lblUG3,lblUG4,lblUG5,lblUG6,lblUG7,lblUG8};
Label[] lblSpdUG = new Label[] { lblSpdUG1, lblSpdUG2, lblSpdUG3, lblSpdUG4, lblSpdUG5, lblSpdUG6, lblSpdUG7, lblSpdUG8 };
for (int x = 0; x < 8;x++ )
{
string IP = "192.168.135.1" + (x + 1).ToString();
var ping = new Ping();
var reply = ping.Send(IP, 10 * 1000);
LabelUG[x].Text = "POSBMS10" + x.ToString();
if (reply.Status == IPStatus.Success)
{
lblSpdUG[x].Text = reply.RoundtripTime.ToString() + " " + "ms";
panelUG[x].BackColor = Color.FromName("Lime");
}
else
{
lblSpdUG[x].Text = "Nonaktif";
panelUG[x].BackColor = Color.FromName("ButtonHighlight");
}
}
}
Without a good, minimal, complete code example, it's hard to know for sure how to best answer your question. But it looks like you are trying to ping eight different servers, which are represented by eight set of controls in your form.
If that is correct, then I agree with commenter Hans Passant that you should be using the SendPingAsync() method instead. This will allow you to execute the pings asynchronously, without blocking the UI thread, so that your program can remain responsive.
Because you are dealing with eight different servers, it makes sense to me that you should execute the eight pings asynchronously. To accomplish this, I would refactor the code a bit, putting the server-specific loop body into a separate method, so that each instance can be run concurrently.
Implementing it that way would look something like this:
private async void CheckPOSUG(object sender, EventArgs e)
{
Panel[] panelUG = new Panel[]{pnlPOSUG1,pnlPOSUG2,pnlPOSUG3,pnlPOSUG4,pnlPOSUG5,pnlPOSUG6,pnlPOSUG7,pnlPOSUG8};
Label[] LabelUG = new Label[]{lblUG1,lblUG2,lblUG3,lblUG4,lblUG5,lblUG6,lblUG7,lblUG8};
Label[] lblSpdUG = new Label[] { lblSpdUG1, lblSpdUG2, lblSpdUG3, lblSpdUG4, lblSpdUG5, lblSpdUG6, lblSpdUG7, lblSpdUG8 };
Task[] tasks = new Task[8];
for (int x = 0; x < 8; x++)
{
tasks[x] = PingServer(x, panelUG[x], LabelUG[x], lblSpdUG[x]);
}
try
{
await Task.WhenAll(tasks);
}
catch (Exception e)
{
// handle as appropriate, e.g. log and exit program,
// report expected, non-fatal exceptions, etc.
}
}
async Task PingServer(int index, Panel panel, Label ugLabel, Label spdLabel)
{
// NOTE: String concatenation will automatically convert
// non-string operands by calling calling ToString()
string IP = "192.168.135.1" + (index + 1);
var ping = new Ping();
var reply = await ping.SendPingAsync(IP, 10 * 1000);
ugLabel.Text = "POSBMS10" + x;
if (reply.Status == IPStatus.Success)
{
spdLabel.Text = reply.RoundtripTime + " ms";
// The Color struct already has named properties for known colors,
// so no need to pass a string to look Lime up.
panel.BackColor = Color.Lime;
}
else
{
spdLabel.Text = "Nonaktif";
panel.BackColor = Color.FromName("ButtonHighlight");
}
}

C# Async Ping: How to avoid an out of memory exception?

Question: I want to search the subnet for all computers in it.
So I send a ping to all IP addresses in the subnet.
The problem is it works fine if I only scan 192.168.0.".
But if I scan 192.168..*", then I get an "Out of memory" exception.
Why ? Do I have to limit the threads, or is the problem the memory consumed by new ping which doesn't get destructed once finished, or do I need to call gc.collect() ?
static void Main(string[] args)
{
string strFromIP = "192.168.0.1";
string strToIP = "192.168.255.255";
Oyster.Math.IntX omiFromIP = 0;
Oyster.Math.IntX omiToIP = 0;
IsValidIP(strFromIP, ref omiFromIP);
IsValidIP(strToIP, ref omiToIP);
for (Oyster.Math.IntX omiThisIP = omiFromIP; omiThisIP <= omiToIP; ++omiThisIP)
{
Console.WriteLine(IPn2IPv4(omiThisIP));
System.Net.IPAddress sniIPaddress = System.Net.IPAddress.Parse(IPn2IPv4(omiThisIP));
SendPingAsync(sniIPaddress);
}
Console.WriteLine(" --- Press any key to continue --- ");
Console.ReadKey();
} // Main
// http://pberblog.com/post/2009/07/21/Multithreaded-ping-sweeping-in-VBnet.aspx
// http://www.cyberciti.biz/faq/how-can-ipv6-address-used-with-webbrowser/#comments
// http://www.kloth.net/services/iplocate.php
// http://bytes.com/topic/php/answers/829679-convert-ipv4-ipv6
// http://stackoverflow.com/questions/1434342/ping-class-sendasync-help
public static void SendPingAsync(System.Net.IPAddress sniIPaddress)
{
int iTimeout = 5000;
System.Net.NetworkInformation.Ping myPing = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingOptions parmPing = new System.Net.NetworkInformation.PingOptions();
System.Threading.AutoResetEvent waiter = new System.Threading.AutoResetEvent(false);
myPing.PingCompleted += new System.Net.NetworkInformation.PingCompletedEventHandler(AsyncPingCompleted);
string data = "ABC";
byte[] dataBuffer = Encoding.ASCII.GetBytes(data);
parmPing.DontFragment = true;
parmPing.Ttl = 32;
myPing.SendAsync(sniIPaddress, iTimeout, dataBuffer, parmPing, waiter);
//waiter.WaitOne();
}
private static void AsyncPingCompleted(Object sender, System.Net.NetworkInformation.PingCompletedEventArgs e)
{
System.Net.NetworkInformation.PingReply reply = e.Reply;
((System.Threading.AutoResetEvent)e.UserState).Set();
if (reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("Roundtrip time: {0}", reply.RoundtripTime);
}
}
According to this thread, System.Net.NetworkInformation.Ping seems to allocate one thread per async request, and "ping-sweeping a class-B network creates 100's of threads and eventually results in an out-of-memory error."
The workaround that person used was to write their own implementation using raw sockets. You don't have to do that in F#, of course, but there are a number of advantages in doing so.
First: Only start like 1000 pings the first time (in the loop in Main)
Second: Move the following parameters to Program class (member variables)
Oyster.Math.IntX omiFromIP = 0;
Oyster.Math.IntX omiToIP = 0;
Oyster.Math.IntX omiCurrentIp = 0;
object syncLock = new object();
Third: In AsyncPingCompleted do something like this in the bottom:
public void AsyncPingCompleted (bla bla bla)
{
//[..other code..]
lock (syncLock)
{
if (omiToIP < omiCurrentIp)
{
++omiCurrentIp;
System.Net.IPAddress sniIPaddress = System.Net.IPAddress.Parse(IPn2IPv4(omiCurrentIp));
SendPingAsync(sniIPaddress);
}
}
}
Update with complete code example
public class Example
{
// Number of pings that can be pending at the same time
private const int InitalRequests = 10000;
// variables from your Main method
private Oyster.Math.IntX _omiFromIP = 0;
private Oyster.Math.IntX _omiToIP = 0;
private Oyster.Math.IntX _omiCurrentIp = 0;
// synchronoize so that two threads
// cannot ping the same IP.
private object _syncLock = new object();
static void Main(string[] args)
{
string strFromIP = "192.168.0.1";
string strToIP = "192.168.255.255";
IsValidIP(strFromIP, ref _omiFromIP);
IsValidIP(strToIP, ref _omiToIP);
for (_omiCurrentIp = _omiFromIP; _omiCurrentIp <= _omiFromIP + InitalRequests; ++_omiCurrentIp)
{
Console.WriteLine(IPn2IPv4(_omiCurrentIp));
System.Net.IPAddress sniIPaddress = System.Net.IPAddress.Parse(IPn2IPv4(_omiCurrentIp));
SendPingAsync(sniIPaddress);
}
Console.WriteLine(" --- Press any key to continue --- ");
Console.ReadKey();
} // Main
// http://pberblog.com/post/2009/07/21/Multithreaded-ping-sweeping-in-VBnet.aspx
// http://www.cyberciti.biz/faq/how-can-ipv6-address-used-with-webbrowser/#comments
// http://www.kloth.net/services/iplocate.php
// http://bytes.com/topic/php/answers/829679-convert-ipv4-ipv6
// http://stackoverflow.com/questions/1434342/ping-class-sendasync-help
public void SendPingAsync(System.Net.IPAddress sniIPaddress)
{
int iTimeout = 5000;
System.Net.NetworkInformation.Ping myPing = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingOptions parmPing = new System.Net.NetworkInformation.PingOptions();
System.Threading.AutoResetEvent waiter = new System.Threading.AutoResetEvent(false);
myPing.PingCompleted += new System.Net.NetworkInformation.PingCompletedEventHandler(AsyncPingCompleted);
string data = "ABC";
byte[] dataBuffer = Encoding.ASCII.GetBytes(data);
parmPing.DontFragment = true;
parmPing.Ttl = 32;
myPing.SendAsync(sniIPaddress, iTimeout, dataBuffer, parmPing, waiter);
//waiter.WaitOne();
}
private void AsyncPingCompleted(Object sender, System.Net.NetworkInformation.PingCompletedEventArgs e)
{
System.Net.NetworkInformation.PingReply reply = e.Reply;
((System.Threading.AutoResetEvent)e.UserState).Set();
if (reply.Status == System.Net.NetworkInformation.IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("Roundtrip time: {0}", reply.RoundtripTime);
}
// Keep starting those async pings until all ips have been invoked.
lock (_syncLock)
{
if (_omiToIP < _omiCurrentIp)
{
++_omiCurrentIp;
System.Net.IPAddress sniIPaddress = System.Net.IPAddress.Parse(IPn2IPv4(_omiCurrentIp));
SendPingAsync(sniIPaddress);
}
}
}
}
I guess the problem is that you are spawning roughly 63K ping requests near-simultaneously. Without further memory profiling it is hard to say which parts consume the memory. You are working with network resources, which probably are limited. Throttling the number of active pings will ease the use of local resources, and also network traffic.
Again I would look into the Task Parallel Library, the Parallel.For construct combined with the Task<T> should make it easy for you.
Note: for .Net 3.5 users, there is hope.
I did something similar to this. The way I solved the problem on my project was to cast the ping instance to IDisposable:
(myPing as IDisposable).Dispose()
So get a list of say 254 ping instances running asynchronously (X.X.X.1/254) and keep track of when all of them have reported in. When they have, iterate through your list of ping instances, run the above code on each instance, and then dump the list.
Works like a charm.
pseudo-code
do
if pings_running > 100 then
sleep 100ms.
else
start ping
endif
loop while morepings
Finally... No ping requried at all...
http://www.codeproject.com/KB/cs/c__ip_scanner.aspx
All I needed to do is to make it thread-safe for debugging.
Changing Add to:
void Add( string m )
{
Invoke(new MethodInvoker(
delegate
{
add.Items.Add(m);
}));
//add.Items.Add( m );
}
Private Sub Add(m As String)
Invoke(New MethodInvoker(Function() Do
add.Items.Add(m)
End Function))
'add.Items.Add(m);'
End Sub

Categories