This question already has answers here:
What is the best way to check for Internet connectivity using .NET?
(27 answers)
Closed 8 years ago.
Can you please tell me if there is a way to check if there is a internet connection in my computer when my C# program is running. For a simple example, if internet is working, I would output a message box saying Internet is available. else I would output a message saying, Internet is unavailable.
Without using the library function to see if network is available (since this doesn't check internet connectivity)
System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()
Or without opening a webpage and seeing if it's return data
using (WebClient client = new WebClient())
htmlCode = client.DownloadString("http://google.com");
Because both of these above methods don't suit my needs.
a little shorter version:
public static bool CheckForInternetConnection()
{
try
{
using (var client = new WebClient())
using (var stream = client.OpenRead("http://www.google.com"))
{
return true;
}
}
catch
{
return false;
}
}
Another option is:
Ping myPing = new Ping();
String host = "google.com";
byte[] buffer = new byte[32];
int timeout = 1000;
PingOptions pingOptions = new PingOptions();
PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
if (reply.Status == IPStatus.Success) {
// presumably online
}
You can find a broader discussion here
Consider the following code snippet...
Ping myPing = new Ping();
String host = "google.com";
byte[] buffer = new byte[32];
int timeout = 1000;
PingOptions pingOptions = new PingOptions();
PingReply reply = myPing.Send(host, timeout, buffer, pingOptions);
if (reply.Status == IPStatus.Success)
{
// presumably online
}
Good Luck!
just wrote async functions to do that:
private void myPingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
return;
if (e.Error != null)
return;
if (e.Reply.Status == IPStatus.Success)
{
//ok connected to internet, do something...
}
}
private void checkInternet()
{
Ping myPing = new Ping();
myPing.PingCompleted += new PingCompletedEventHandler(myPingCompletedCallback);
try
{
myPing.SendAsync("google.com", 3000 /*3 secs timeout*/, new byte[32], new PingOptions(64, true));
}
catch
{
}
}
My NetworkMonitor class now provides this (based on other responses here):
public bool IsInternetAvailable
{
get { return IsNetworkAvailable && _CanPingGoogle(); }
}
private static bool _CanPingGoogle()
{
const int timeout = 1000;
const string host = "google.com";
var ping = new Ping();
var buffer = new byte[32];
var pingOptions = new PingOptions();
try {
var reply = ping.Send(host, timeout, buffer, pingOptions);
return (reply != null && reply.Status == IPStatus.Success);
}
catch (Exception) {
return false;
}
}
This is my approach;
Check that a network connection is available, if it isn't then we wont be able to connect to another host.
Check if we can connect to some major hosts. Use a fallback just in case that site isn't available.
public static bool ConnectToInternet(int timeout_per_host_millis = 1000, string[] hosts_to_ping = null)
{
bool network_available = System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
if (network_available)
{
string[] hosts = hosts_to_ping ?? new string[] { "www.google.com", "www.facebook.com" };
Ping p = new Ping();
foreach (string host in hosts)
{
try
{
PingReply r = p.Send(host, timeout_per_host_millis);
if (r.Status == IPStatus.Success)
return true;
}
catch { }
}
}
return false;
}
Notes:
Don't use too many hosts when reaching out, weigh up the cost in time of making all the pings against the diminishing likelihood of success.
If we send the ping to a certain that host we intend to connect to later (eg a http request) a returned ping doesn't mean we are connected to that particular host. Consider what would happen if the host is blocked. eg Facebook is blocked in Iran,China,... Does that ISP return the ping?
A DNS request wont be sufficient as it may be cached
public static bool HasConnection()
{
try
{
System.Net.IPHostEntry i = System.Net.Dns.GetHostEntry("www.google.com");
return true;
}
catch
{
return false;
}
}
Related
Is there anyway to check if a computer is turned on / off using C#?
I have tried using this.
private static bool IsMachineUp(string hostName)
{
bool retVal = false;
try
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 120;
PingReply reply = pingSender.Send(hostName, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
retVal = true;
}
}
catch (Exception ex)
{
retVal = false;
Console.WriteLine(ex.Message);
}
return retVal;
}
But the problem is it always returns true when finding an ip of internal network and always returns false when finding by external network.
Is there any other way?? Just to determine whether a pc is turned on or off.
Or if external network is not available then is there a way to find if the ip of external network is actually used by a computer?
I am trying to make a scan wether the pc is online or offline.
But my current code is way to slow to scan with a good performance as if an computer is offline there is a delay of 3 to 5 seconds.
I even added the timeout parameter set as 500 but it still takes more than 3 seconds if a computer is offline.
public bool PingComputer(string computername)
{
bool check = false;
Ping ping = new Ping();
try
{
PingReply reply = ping.Send(computername, 500);
check = reply.Status == IPStatus.Success;
}
catch (PingException)
{
}
return check;
}
I also already read about asynchron pings but i couldĀ“nt find a suitable solution yet that simply returns true if computer is online or false if it is offline.
Thanks in advance.
If you pretended to Ping a list of Computers you can use Parallel or use async Task.
I tested both methods bellow with the same 77 IPs. Used variable sec = 3.
Tasks toke 00:00:02.7146249
Parallel toke 00:00:05.9941404
To use the methods
Dictionary<string, bool> pingsReturn = await Network.PingListAsync(dictionary,3);
I can give you the 2 examples:
Task
public static async Task<Dictionary<string, bool>> PingListAsync(Dictionary<string, bool> HostList, int sec = 3)
{
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
// set a quick TTL
PingOptions options = new PingOptions(20, true);
// internal support Task to handle Ping Exceptions like "host not found"
async Task<KeyValuePair<string, bool>> PingHost(string host)
{
try
{
var pingresult = await Task.Run(() => new Ping().SendPingAsync(host, sec * 1000, buffer, options));
//t.Wait();
if (pingresult.Status == IPStatus.Success)
return new KeyValuePair<string, bool>(host, true);
else
return new KeyValuePair<string, bool>(host, false);
}
catch
{
return new KeyValuePair<string, bool>(host, false);
}
}
//Using Tasks >>
var watch = new Stopwatch();
watch.Start();
var tasksb = HostList.Select(HostName => PingHost(HostName.Key.ToString()));
var pinglist = await Task.WhenAll(tasksb);
foreach (var pingreply in pinglist)
{
HostList[pingreply.Key] = pingreply.Value;
}
watch.Stop();
Log.Debug("PingList (Tasks) Time elapsed: " + watch.Elapsed);
//Using Tasks <<
return HostList;
}
Parallel
public static async Task<Dictionary<string, bool>> PingListAsync(Dictionary<string, bool> HostList, int sec = 3)
{
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
// set a quick TTL
PingOptions options = new PingOptions(20, true);
//Using Parallel >>
watch = new Stopwatch();
watch.Start();
// avoid exception "Collection was modified; enumeration operation may not execute."
// we need new dictionary and add values
Dictionary<string, bool> dictionary = new Dictionary<string, bool>();
Parallel.ForEach(HostList.Keys, (currHost) =>
{
try
{
var pingReply = new Ping().Send(currHost, sec * 1000, buffer, options);
if (pingReply.Status == IPStatus.Success)
dictionary.Add(currHost, true);
else
dictionary.Add(currHost, false);
}
catch
{
// handle Ping Exceptions like "host not found"
dictionary.Add(currHost, false);
}
});
watch.Stop();
Log.Debug("PingList (Parallel) Time elapsed: " + watch.Elapsed);
//Using Parallel <<
return dictionary;
}
PS - I know this is an old question, but is still valid.
I was struggling with a problem for a long time. I was using unity and I want to ping my server and router. I was using UnityPing class at the beginning and it works fine for the most of devices, but when I testing on Google Pixel(Android 7.1) it always return -1. So I tried to use System.Net.NetworkInformation to ping my server. here is my code:
private void PingToServer()
{
AutoResetEvent waiter = new AutoResetEvent(false);
System.Net.NetworkInformation.Ping pingSender = new System.Net.NetworkInformation.Ping();
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 10000;
PingOptions options = new PingOptions(64, true);
IPAddress address = IPAddress.Parse("119.81.194.57");
pingSender.SendAsync(address, timeout, buffer, options, waiter);
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
((AutoResetEvent)e.UserState).Set();
}
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
int pingTime = (int)reply.RoundtripTime;
UnityEngine.Debug.Log(reply.RoundtripTime);
((AutoResetEvent)e.UserState).Set();
}
And It always return a RoundripTime which seems like a number make sense, but when I try to ping another ip address which is not available to reach or even turn off the internet it always return a RoundripTime with reply.status equals to IPStatus.Success. Now I'm confused, did I really ping to my remote server or not?
I did chekced some other similar questions, and it doesn't solved the problem. Some answers suggest to use SendPingAsync instead of SendAsync, but that is not possible for unity.
I have button.click event where i have this code ... and it works fine
AutoResetEvent waiter = new AutoResetEvent(false);
Ping pingSender = new Ping();
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 100;
PingOptions options = new PingOptions(64, true);
IPAddress address = IPAddress.Parse("YourTestIP");
PingReply reply = pingSender.Send(address, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
MessageBox.Show(reply.Address.ToString());
}
I want to check if the the proxies in my list are working before using them, is it possible?
It's easy for HTTP/HTTPS since you only have to use the webclient but for socks?
I tough this could work for all
public static bool SoketConnect(string addresse)
{
string[] proxy = addresse.Split(':');
if (proxy.Count() == 2)
{
string host = proxy[0];
int port = Convert.ToInt32(proxy[1]);
var is_success = false;
try
{
var connsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connsock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 200);
System.Threading.Thread.Sleep(500);
var hip = IPAddress.Parse(host);
var ipep = new IPEndPoint(hip, port);
connsock.Connect(ipep);
try
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("ping");
byte[] inStream = new byte[100];
connsock.Send(outStream);
connsock.ReceiveTimeout = 500;
connsock.Receive(inStream);
string message = System.Text.Encoding.ASCII.GetString(inStream);
foreach (var bytes in inStream)
{
if (bytes != 0)
{
is_success = true;
break;
}
}
connsock.Disconnect(false);
}
catch(Exception ex)
{
is_success = false;
}
connsock.Close();
}
catch (Exception ex)
{
is_success = false;
}
return is_success;
}
else
return false;
}
but i always get the exception
"The underlying connection was closed: The connection was closed
unexpectedly." System.Net.WebException
tldr; How to check if my socks proxies are working ( Which comes back to how to use a socks proxy)
EDIT: still doesn't help,need an answer
EDIT2 : Only pinging the proxy isn't the right thing to do
As far as I know you have to use them to see if they are working. I suggeset one of the following:
ping - With Ping class in:
using System.Net.NetworkInformation;
private static bool CanPing(string address)
{
Ping myping = new Ping();
try
{
PingReply reply = myping.Send(address, 2000);
if (reply == null)
return false;
return (reply.Status == IPStatus.Success);
}
catch (PingException e)
{
return false;
}
}
Do a "Whats my IP?" through a proxy:
public static void TestProxies()
{
var lowp = new List<WebProxy> { new WebProxy("1.2.3.4", 8080), new WebProxy("5.6.7.8", 80) };
Parallel.ForEach(lowp, wp => {
var success = false;
var errorMsg = "";
var sw = new Stopwatch();
try
{
sw.Start();
var response = new RestClient
{
BaseUrl = "https://webapi.theproxisright.com/",
Proxy = wp
}.Execute(new RestRequest { Resource = "api/ip", Method = Method.GET, Timeout = 10000, RequestFormat = DataFormat.Json });
if (response.ErrorException != null)
throw response.ErrorException;
success = (response.Content == wp.Address.Host);
}
catch (Exception ex)
{
errorMsg = ex.Message;
}
finally
{
sw.Stop();
}
});
}
Does anyone have C# code handy for doing a ping and traceroute to a target computer? I am looking for a pure code solution, not what I'm doing now, which is invoking the ping.exe and tracert.exe program and parsing the output. I would like something more robust.
Given that I had to write a TraceRoute class today I figured I might as well share the source code.
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Text;
using System.Net;
namespace Answer
{
public class TraceRoute
{
private const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
public static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress)
{
return GetTraceRoute(hostNameOrAddress, 1);
}
private static IEnumerable<IPAddress> GetTraceRoute(string hostNameOrAddress, int ttl)
{
Ping pinger = new Ping();
PingOptions pingerOptions = new PingOptions(ttl, true);
int timeout = 10000;
byte[] buffer = Encoding.ASCII.GetBytes(Data);
PingReply reply = default(PingReply);
reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions);
List<IPAddress> result = new List<IPAddress>();
if (reply.Status == IPStatus.Success)
{
result.Add(reply.Address);
}
else if (reply.Status == IPStatus.TtlExpired || reply.Status == IPStatus.TimedOut)
{
//add the currently returned address if an address was found with this TTL
if (reply.Status == IPStatus.TtlExpired) result.Add(reply.Address);
//recurse to get the next address...
IEnumerable<IPAddress> tempResult = default(IEnumerable<IPAddress>);
tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1);
result.AddRange(tempResult);
}
else
{
//failure
}
return result;
}
}
}
And a VB version for anyone that wants/needs it
Public Class TraceRoute
Private Const Data As String = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Public Shared Function GetTraceRoute(ByVal hostNameOrAddress As String) As IEnumerable(Of IPAddress)
Return GetTraceRoute(hostNameOrAddress, 1)
End Function
Private Shared Function GetTraceRoute(ByVal hostNameOrAddress As String, ByVal ttl As Integer) As IEnumerable(Of IPAddress)
Dim pinger As Ping = New Ping
Dim pingerOptions As PingOptions = New PingOptions(ttl, True)
Dim timeout As Integer = 10000
Dim buffer() As Byte = Encoding.ASCII.GetBytes(Data)
Dim reply As PingReply
reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions)
Dim result As List(Of IPAddress) = New List(Of IPAddress)
If reply.Status = IPStatus.Success Then
result.Add(reply.Address)
ElseIf reply.Status = IPStatus.TtlExpired Then
'add the currently returned address
result.Add(reply.Address)
'recurse to get the next address...
Dim tempResult As IEnumerable(Of IPAddress)
tempResult = GetTraceRoute(hostNameOrAddress, ttl + 1)
result.AddRange(tempResult)
Else
'failure
End If
Return result
End Function
End Class
This implementation is simple, lazy (properly enumerable) and it will not go on searching forever (maxTTL) like some of the other answers.
public static IEnumerable<IPAddress> GetTraceRoute(string hostname)
{
// following are similar to the defaults in the "traceroute" unix command.
const int timeout = 10000;
const int maxTTL = 30;
const int bufferSize = 32;
byte[] buffer = new byte[bufferSize];
new Random().NextBytes(buffer);
using (var pinger = new Ping())
{
for (int ttl = 1; ttl <= maxTTL; ttl++)
{
PingOptions options = new PingOptions(ttl, true);
PingReply reply = pinger.Send(hostname, timeout, buffer, options);
// we've found a route at this ttl
if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired)
yield return reply.Address;
// if we reach a status other than expired or timed out, we're done searching or there has been an error
if (reply.Status != IPStatus.TtlExpired && reply.Status != IPStatus.TimedOut)
break;
}
}
}
Although the Base Class Library includes Ping, the BCL does not include any tracert functionality.
However, a quick search reveals two open-source attempts, the first in C# the second in C++:
http://www.codeproject.com/KB/IP/tracert.aspx
http://www.codeguru.com/Cpp/I-N/network/basicnetworkoperations/article.php/c5457/
For the ping part, take a look at the Ping class on MSDN.
This is the most efficient way I could think of.
Please vote it up if you like it so others can benefit.
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
namespace NetRouteAnalysis
{
class Program
{
static void Main(string[] args)
{
var route = TraceRoute.GetTraceRoute("8.8.8.8")
foreach (var step in route)
{
Console.WriteLine($"{step.Address,-20} {step.Status,-20} \t{step.RoundtripTime} ms");
}
}
}
public static class TraceRoute
{
public static IEnumerable<PingReply> GetTraceRoute(string hostnameOrIp)
{
// Initial variables
var limit = 1000;
var buffer = new byte[32];
var pingOpts = new PingOptions(1, true);
var ping = new Ping();
// Result holder.
PingReply result = null;
do
{
result = ping.Send(hostnameOrIp, 4000, buffer, pingOpts);
pingOpts = new PingOptions(pingOpts.Ttl + 1, pingOpts.DontFragment);
if (result.Status != IPStatus.TimedOut)
{
yield return result;
}
}
while (result.Status != IPStatus.Success && pingOpts.Ttl < limit);
}
}
}
Ping: We can use the Ping class built into the .NET Framework.
Instantiate a Ping and subscribe to the PingCompleted event:
Ping pingSender = new Ping();
pingSender.PingCompleted += PingCompletedCallback;
Add code to configure and action the ping, e.g.:
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
string who = "www.google.com";
AutoResetEvent waiter = new AutoResetEvent(false);
int timeout = 12000;
PingOptions options = new PingOptions(64, true);
pingSender.SendAsync(who, timeout, buffer, options, waiter);
Add a PingCompletedEventHandler:
public static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
... Do stuff here
}
Code-dump of a full working example, based on MSDN's example:
public static void Main(string[] args)
{
string who = "www.google.com";
AutoResetEvent waiter = new AutoResetEvent(false);
Ping 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.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
// Wait 12 seconds for a reply.
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.
PingOptions 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.
pingSender.SendAsync(who, timeout, buffer, options, waiter);
// Prevent this example application from ending.
// A real application should do something useful
// when possible.
waiter.WaitOne();
Console.WriteLine("Ping example completed.");
}
public 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();
}
Console.WriteLine($"Roundtrip Time: {e.Reply.RoundtripTime}");
// Let the main thread resume.
((AutoResetEvent)e.UserState).Set();
}
As am improvement to Scotts code answer above, I found that his solution doesn't work if the route tapers off into nothing before reaching the destination - it never returns. A better solution with at least a partial route could be this (which I've tested and it works well). You can change the '20' in the for loop to something bigger or smaller or try to detect if it's taking too long if you want to control the number of iterations some other way. Full credit to Scott for the original code - thanks.
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Text;
using System.Net;
...
public static void TraceRoute(string hostNameOrAddress)
{
for (int i = 1; i < 20; i++)
{
IPAddress ip = GetTraceRoute(hostNameOrAddress, i);
if(ip == null)
{
break;
}
Console.WriteLine(ip.ToString());
}
}
private static IPAddress GetTraceRoute(string hostNameOrAddress, int ttl)
{
const string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
Ping pinger = new Ping();
PingOptions pingerOptions = new PingOptions(ttl, true);
int timeout = 10000;
byte[] buffer = Encoding.ASCII.GetBytes(Data);
PingReply reply = default(PingReply);
reply = pinger.Send(hostNameOrAddress, timeout, buffer, pingerOptions);
List<IPAddress> result = new List<IPAddress>();
if (reply.Status == IPStatus.Success || reply.Status == IPStatus.TtlExpired)
{
return reply.Address;
}
else
{
return null;
}
}