Best practice to check if connected to the internet. Desktop app and web service

I am following the WebServices example project and am moving along nicely. I thought to test to see what would happen if I disconnected from the internet and attempted the connection. Got a “no internet connection” error on the SendSync line

Then I thought to ping the server and get the HTTPStatusCode as in below from the docs (change the URL to my server’s name and the method, but not at the computer now, and I don’t remember it), but this also failed with the error

Var content As String
content = MyConnection.SendSync("GET", "http://127.0.0.1:8080/GetData", 30)
Var status As Integer = MyConnection.HTTPStatusCode

If status = 200 then
//Proceed with code
End if

So what is the best way to make sure the user is connected? My desktop app may be used offline for the most part but will need to get/send data periodically, and if not connected, it will hold onto the data and shoot it up once connected

The web server app is on Xojo Cloud, and the calling app is a desktop, tested only on Mac thus far but will be for Windows too.

You can use a try/catch block to capture that error and use it to confirm that you are offline.

Thanks for the response Christian. I always forget about Try…Catch. Unfortunately, this did not seem to work. Perhaps I have it set up incorrectly?

try
  Var jCode As New JSONItem
  jCode.Value("RegCodes") = txtCode.Text
  
  XMEConnector.SetRequestContent(jCode.ToString, "application/json")
  XMEConnector.AllowCertificateValidation = False
  Var content As String = XMEConnector.SendSync("POST", "https://XCMiddleEarth.xojocloud.net/DeleteRegCode")
  
  content = content.DefineEncoding(Encodings.UTF8)
  
  Var json As New JSONItem(content)
  
  If json.HasName("DeleteRegCode") Then
    Var jCodeData As JSONItem = json.Value("DeleteRegCode")
    
    if jCodeData.Value("Deleted") = "yes" then
      ResultsArea.AddText("code deleted" + EndOfLine)
    else
      ResultsArea.AddText("This code was not DELETED")
    End If
  End If
catch e as NetworkException
  ResultsArea.AddText("NOT CONNECTED" + EndOfLine + e.Message)
  Return
end try

You need to continue debugging because you have the IDE to stop on exceptions (that’s why it stopped there), once you resume you will see if the code jumps to the catch section.

2 Likes

Oh geez! Haha, that was it!

You can add a #Pragma BreakOnExceptions False just before your try block to avoid this, but only once you’re sure your other logic is sound. Don’t forget to set it back to True later in the code to protect your future self’s sanity! xD

1 Like

Thanks for this! After seeing Alberto’s response, I found the #Pragma usage in the Try/Catch section of the docs and tested it with that

My personal preference is to set it back to Default (instead of True) so that I can use the IDE menu options to control the default during debug sessions. And like all #Pragmas, it only stays in scope until the end of that method so there is no need to set it back if the method is ending anyway.

This is not true for BreakOnExceptions and why I strongly recommend against that one!!

I’ve had BreakOnExceptions set by OPC in one method cause the debugger not to stop in my own code called from their event handler. Was an effing nightmare, and I cursed the whole day long.

Edit: Here’s an example project to show the problem that can happen: exception-warning.xojo_xml_project

2 Likes

What??? I’ve been using Xojo for years and did not know that, and assumed this went out of scope at the end of the method. I’ll have to revisit projects where I use it and explicitly put back to Default. But then all the more reason to use Default instead of True (IMHO anyway).

1 Like

At the end of the method when exiting to a “higher level” in the stack, but it affects everything “below” it in the stack. See the example project I created.

What I use on Windows

Public Function IsInternetConnected() As Boolean
  #If TargetWindows Then
    Declare Function InternetGetConnectedState Lib "wininet" (ByRef lpdwFlags As UInt32, dwReserved As UInt32) As Boolean
    
    Var flags As UInt32
    Return InternetGetConnectedState(flags, 0)
    
  #Endif
End Function

Does that provide a different result than Network.IsConnected?

Not sure.

Network.IsConnected tells you about the local network, not whether you have an internet connection.

3 Likes

I’m following along here as well as I too, would like to find the best known Xojo methods for checking for Internet connectivity.

At least natively in Apple-land, in the past you’d use Reachability (aka SCNetworkReachability) or even AFNetworking (now deprecated in lieu of AlmoFire). Alas as most frameworks go, @Christian_Schmitz has an MBS wrapper for SCNetworkReachability as SCNetworkReachabilityMBS for those who use MBS on Apple. Alternatively, it looks like macoslib has Reachability baked in as well.

Not really sure what would be used in Windows-land though, but I’m highly interested to find out if anyone has some thoughts.

EDITED: Strike that request on Windows as Sveinn has the answer up above. I just need to learn to read. :wink:

Also as a follow up, it looks like the Windows Functionality Suite (WFS) has the InternetGetConnectedState function baked in as well.

Not to gravedig this post but I went and tested my question from earlier:

Does [the declare] provide a different result than Network.IsConnected?

The answer is that it provides the same result. Network, with no internet, the declare still says is connected:

Network.IsConnected: True
wininet.InternetGetConnectedState: True

Test project: NetworkTest.xojo_xml_project

1 Like

Very good to know Tim.

On a separate note, I’m still left scratching my head a bit though in that I haven’t stumbled across any truly cross-platform solutions here especially as Apple and Microsoft have engineered things differently…

macOS

  • Reachability and the like will tell you if you can traverse the network to reach a server.
  • Event callbacks happen when the network state changes (e.g. super helpful so that you can adjust your app workflows).
  • This doesn’t necessarily imply one is on the Internet though in that a server can be reachable on say a private LAN without Internet access.

Windows

  • InternetGetConnectedState will tell you if the Internet is available.
  • This doesn’t imply that the server you want to get to though is actually available or traversable to.

Linux

  • We haven’t covered Linux yet in any of these discussions, but this would probably be helpful for many.

Having a single high level solution to cover the following would be great…

  1. Internet availability
  2. Ability to traverse to a specific FQDN/IP address
    2.1 Bonus points to be able to check to see if the server itself is responding (maybe a simple GET or HEAD request assuming some kind of a HTTP backend?)
  3. And of course having all of this event driven so that you can be notified when either 1 or 2 changes.

@Christian_Schmitz this smells like it could be a feature request for MBS. Especially as MBS has much of the lower level calls already created (although it’s unknown to me if Linux is covered).

@Here & maybe @Jeremie_L As I haven’t spent a bunch of time in the iOS target of Xojo, I’ll ask a related question. At least back in the old days, Apple required your App Store apps to check for network connectivity upon startup and this was one of the validation checks they would do before approving your app for publishing. Assuming they’re still doing something similar these days, how are the Xojo iOS folks addressing this requirement? Xojo code? Declares? Something else?

1 Like

Just to clarify, the test showed that InternetGetConnectedState will tell you if the LAN is available, but does not actually test internet connection.

  1. As I mention in the other thread, you really should just attempt your request and then handle the error. In most cases you’re just going to relay to the user what the NetworkException code and message are.
  2. Network.LookupIPAddress(sDNSAddress as String) will resolve a FQDN
    2.1. URLConnection.Send("HEAD", url)
  3. URLConnection.Send is event driven, LookupIPAddress is not though. FWIW, making the attempt and then handling the error is also an event driven design.

This is meant to be helpful, not a critique. It seems to me that the tools exist to properly handle the situation. Am I missing a piece of the puzzle?