Has been discussed before:
check whether Internet connection is available with C#
How to determine if network interface is connected to the Internet (i. e. the computer is online)
What is the best way to check for Internet connectivity using .NET?
Testing for internet connectivity across a specific network adapter
Task: To scan through the network interfaces on the computer and on the fly check for internet availability. Turned out to be annoying.
First we walk through the interfaces, using the pseudo code below (translated from the APL language). Naturally it would be convenient to test for internet connection inside the loop, as the interface is handy anyway.
pingpong = #.Net.NetworkInformation.Ping.New // An instance of the Ping class
:For i :In #.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces
(Change the current namespace to i -> everything hereafter happens for "i")
:If NetworkInterfaceType.(⎕THIS = Ethernet)
:OrIf NetworkInterfaceType.(⎕THIS = Wireless80211) // Skip others, like Loopback, AsymmetricDsl, Atm etc
(Get stuff like GetIPProperties.UnicastAddresses, GetIPProperties.GatewayAddresses, blabla)
// Check the "OperationalStatus" property (not ok for internet detection)
dumb = OperationalStatus.(⎕THIS = Up)
// Do a blocking call on pingpong to Google's 8.8.8.8 (not ok for internet detection)
dumb = pingpong.Send (#.Net.IPAddress.New Convert.ToInt64 256⊥⌽8 8 8 8) 1000 (#.Text.Encoding.ASCII.GetBytes 32⍴' ') (#.NetworkInformation.PingOptions.New 128 1) // Ttl, DontFragment
:End
:End
Problematics in above:
OperationalStatus Enumeration
Only reveals that the interface is ready, not that it has a functional connection.pingpong.Send blabla - the dotnet Ping Class
Would be perfect, but does not Send over the desired interface "i". Instead Windows uses a default interface. So this won't tell us if interface "i" has internet connection.
What then?
System.Runtime.InteropServices.DllImport("Wininet.dll") WinINet Reference
Provides some functionality that .net does not, but... This is just not the way to go in year 2016, imho.ICMP echo request - Simple Ping tutorial
Coded the needed ICMP packet transmission. It must happen over a raw socket. Problem: Raw sockets require elevated UAC which is unacceptable. We cannot force clients to Run our app as Admin :-).
Additional problem: Limiting the hops. I had wished to use a TTL of like 4, that would be sufficient for getting the packet to leave the local environment. TTL=4 hits the ISP infra, where it reaches 0 and gets boomeranged. But the NAT-like behaviour in various devices and firewalls only accept packets from the target. Ie. if we ping 8.8.8.8 with a TTL=4, we get a reply from an intermediate IP address, which the firewall blocks as it isn't 8.8.8.8. The ICMP request works perfectly well if TTL is high and the reply comes from Google, otherwise my code has a timeout. This is irrelevant, as the elevated UAC makes this a no go anyway.UDP ping
UDP ping works by sending a UDP packet to a (hopefully unused) port at the remote endpoint and wishing to get a ICMP Destination unreachable back (which would tell us that there is someone -> we have internet). The problem is that the endpoint may be totally uninformative, if we happen to hit a port that is in use (and remember, this should be a generic ping utility, pinging a public, yet to be selected/re-selected target). We cannot know in advance how the ports behave.TCP SYN - example
TCP ping works by making the first steps in initiating a TCP connection. One simply Connects to the IP address (and port!), and should see a transmission like:→ SYN
← SYN,ACK
→ ACK
→ FIN,ACK
← FIN,ACK
→ ACK
after which one terminates the connection. A timeout means nobody's there. I just find this somewhat dubious. If i TCP-connect-attempt to port 80 on a remote endpoint, how could i even assume that it replies? How do we know that it will so in 1 year? Simply seems like a weak way to determine internet connection, by performing a targeted TCP connect. Remote endpoints do not gracefully accept TCP connections, instead they tend to focus on blocking.Command line ping.exe
This allows one to specify the local interface with the -S parameter. One can append a >tempfile.txt to the command, execute it from code, read and parse tempfile.txt and silently delete it afterwards. Uuuhhh... is this really the best option? :-) Basically it does what we want: Requires no elevated UAC, allows us to set the interface (ie. the local IP address), allows us to set the limited TTL and it even magically bypasses the firewall (how...?).
I'd be grateful to hear of better ideas for determining internet connection? I am aware of Http requests and Dns lookups - would be nice if there was something a little smarter.