Checking internet Connection using URLConnection

I’m updating some old code: to check an internet connection I used to use this snippet (posted years ago by Michael Bujardet):
Dim http As New HTTPSocket
http.yield = True
dim ih as InternetHeaders = (http.GetHeaders(“https://www.apple.com”, 1))
return (ih <> nil)

The code never fails in its response. Nevertheless I thought of replacing the deprecated HTTPSocket with URLConnection. URLConnection does not accept some of the above parameters, so I concocted the snippet below.

Now, when there is no connection, I get FALSE; yet even when I know that I do have a connection, sometimes I get False (even increasing the yeld time from 1 to 5 or more).
So I think the code actually needs improvements.
Suggestions welcome.

testConnection.xojo_binary_project.zip (4.5 KB)

Since I noticed that when there is no connection I get an exception, after initialising content I go straight to Return TRUE.

Var urlConn As New URLConnection
Var content As String = URLConn.SendSync(“GET”, “https://www.apple.com”, 1)
//Return content <> “”
Return true

Exception
return false

Var uc As New URLConnection
Var internetOk As Boolean = False

Try
  Call uc.SendSync("HEAD", "https://www.apple.com", 2)
  internetOk = True
Catch
End
If not internetOk Then
  Try
    Call uc.SendSync("HEAD", "https://www.google.com", 2)
    internetOk = True
  Catch
  End
End

// Here you know if the internet is ok

break

As a Function:

Function IsInternetOK As Boolean

  #Pragma BreakOnExceptions Off
  
  Var uc As New URLConnection
  
  Try
    Call uc.SendSync("HEAD", "https://www.apple.com", 2)
    Return True
  Catch
  End
  
  Try
    Call uc.SendSync("HEAD", "https://www.google.com", 2)
    Return  True
  Catch
  End
  
  Return False

End Function

Thank you Rick for your better code.
Yet, starting with my connection OFF (and getting FALSE), when I set it ON (see screenshot) even waiting several seconds, I still get FALSE. Only at my second or third attempt I get TRUE.
Since the old HTTPSocket never failed, I guess it is a URLConnection problem.
BTW, I’d emphasise this happens only when I check for a connection SOON AFTER I switch my internet connection ON.
[Edited} Yet Mail or other apps get connected at once.

Perhaps it’s not a problem, but a difference, like the URLConnection needs more resources to be configured/available while the connection is being turned fully on.

I did not intend demonizing URLConnection. So I agree. I could be.

If the computer is connected to the internet was discussed multiple times here on the forum. I also had problems with this. You can’t assume anything. Even worse when Little Snitch or similar are installed some connections might work and others might not.

This is my check:

if IsLittleSnitchInstalled then
  
  Return ConnectedToInternet.LittleSnitchInstalled
  
Else
  
  dim theShell as new Shell
  theShell.Execute "ping -n -q -W 5 -c 1 8.8.8.8"
  If theShell.ExitCode = 0 Then
    Return ConnectedToInternet.IsConnected
  else
    Return ConnectedToInternet.notConnected
  end if
  
end if

As far as I remember there is an Apple framework to do a proper check. This should be available in the MBS plugin.

Your code does not stumble: I mean, it returns “Connected” even after checking a No Connection.
May I ask you which site is the shell pinging?

Google. Which is why I would recommend against that method.

With modern application design you are really just supposed to try your connection and if it fails, handle that. Making preemptive connections to test has fallen out of fashion for so many reasons.

One of which (that Beatrix covers) is network filters that allow users to block individual connections based on where they go. I for one would balk at an application attempting to connect to 8.8.8.8 at launch for no reason at all - in fact I block my VPN software from doing just that.

Yep, I recall people saying that pinging may not be the best idea.

Yup, 8.8.8.8 is Goggle. My users usually are guys who don’t have very much computer experience. In the last years the check was good enough.

This is the class from MBS: Monkeybread Xojo plugin - Example: /MacOSX/NWPathMonitor Test . Haven’t checked that out, yet.

Lots of possibilities including some specific MacOS problem. Can’t see it on a standard Windows OS with the function I provided.

I remember LOTS of discussions due to some new behavior on a MacOS version about missing few initial connections demanding retries for several seconds until that at some point the system weirdly start to become instantaneously responsive. We thought it was a new MacOS bug. Don’t know how this research ended. I do remember @Thom_McGrath running experiments.

I see the behavior / interruption with LAN connections, but it has so far not affected my asynchronous launch time DRM check-in (WAN). Trying again after the initial failure works. For me, it’s frustrating but livable.

What about trying more insistently a bit until that “MacOS warm up” ends, as:

Function IsInternetOK As Boolean

  #Pragma BreakOnExceptions Off
  
  Var uc As New URLConnection
  
  #If DebugBuild
    System.Debuglog "Contacting Google"
  #EndIf
  
  For i As Integer = 1 to 10 // find a safe lower max value if possible
    
    Try
      Call uc.SendSync("HEAD", "https://8.8.8.8", 2)
      Return  True
    Catch
    End
    
    #If DebugBuild
      System.Debuglog "retrial "+i.ToString
    #EndIf

    Thread.SleepCurrent(500)

  Next
  
  Return False

End Function

Now, after the warming up, it works.
But I would not make MacOS the culprit, since the problem affects only URLConnection; in fact browsers and other apps react as soon as the connection-icon (inj the menu-bar) turns ON. HTTPSocket too gets TRUE immediately.

URLConnection is powered by the system. It’s definitely macOS to blame. If you take your code to an older version, the delay isn’t necessary.

1 Like

macOS 11 Big Sur did not exhibit the problem, for instance.
(I upgraded straight from Big Sur to Sequoia, that’s all I can offer)

There is also an issue that if you are behind certain gateways, they may intercept http connections and redirect them to a captive portal. So you can not be sure that an arbitrary response from a website indicates that the user is online.

You should host a script on your own website that responds with whatever query string is passed into it, randomize this in your test, and verify that the response was the same as the request.

If you’re doing all that work, why not just attempt the connection you were going to make anyway? :sweat_smile:

I think that’s the theory we go with these days. Make your connection and if it fails report what happened to the user.

3 Likes

Indeed! That is really the best approach. But in my app, for example, I have an “online/offline” indicator that needs to work without a particular website.

1 Like