Xojo.Net.HTTPSocket problem when Network is not Available. Error Handler freezes the entire App

Hello,

I am using Xojo.Net.HTTPSocket class to perform an asynchronous call of an API.
I have created a module where I have an instance of my class and I call the API using a Timer.

I am trying to check my Application whenever I do not have connection to the Network and
the Socket lags and freezes all the Applicatio for about 10-15 seconds.

The Error Handler receives the error: “The server name or address could not be resolved”
I have checked in both Xojo 2016.r3 and Xojo 2018r4.

Can you please help me with this? I have searched the forum but did not find any answer on something similar.

Thank you in advance.

A search in this forum for internet connection leads to (for example):

https://forum.xojo.com/41073-best-way-to-check-internet-connection/0#p334269

Hi Emile,

The problem here is not how to find out if I have connection to the Internet, which is the easy part, but to find out if the Xojo.Net.HttpSocket can be used asynchronously or not.
The fact that an error on something mentioned as asynchronous freezes the entire app is something that I want to bypass.

Do you have an answer on this or something to propose?

Thank you again for your time.

Is this a debugbuild or build application that has the “freeze”?
As the exception is handled trough the event, possibly the debugger hangs?

I recommend you change to use URLConnection as it seems more robust.

You can check the internet connection trough using:


Dim IPAddress As String
IPAddress = System.Network.LookupIPAddress("wikipedia.org")
If IPAddress <> "" Then
  MessageBox(IPAddress)
// url can be connected to
Else
  MessageBox("An error occurred")
// no internet for this url
End If

Replace wikipedia.org with the domain you want to access

Hi Derk,

I have just checked it on a build application and it freezes too.
I have changed all the Xojo.Net.HTTPSocket to Asynchronous HTTPSecureSocket and it also happens with this socket too.

I am really confused.

Macos has CFHost and windows has DnsQueryEx which are both async, as long as Xojo is using those (which I haven’t checked) then I can’t see why it should be freezing.

Are you having this issue on mac or windows as I can’t seem to replicate it under windows?
Are you able to replicate this on a small demo project? If so, could you share the project so we can check it here?

Just to know if this was a bug and if it was removed since, have-you run your project on 2019r3 (using URLConnection) ?

@Sebastian the best is to use URLConnection. HTTPSecureSocket is now deprecated (Xojo 2019r1)

[quote=471513:@Sebastian Kapellas]Hi Derk,

I have just checked it on a build application and it freezes too.
I have changed all the Xojo.Net.HTTPSocket to Asynchronous HTTPSecureSocket and it also happens with this socket too.

I am really confused.[/quote]

Are you calling a “https://” or “http://” url?
If “http://” you need to add a plist with special keys for macOS.

As you leave alot of details for us, we can only guess. What platform is this? Windows, macos or linux?

Thank you all for your help.

I am working on Windows 10.
I cannot upgrade to Xojo 2019 version for now, because we are using a large framework for database and gui which needs to be upgraded too. (In plans for next month)

I have written some code below to help you understand.
I will try to create a small project later, similiar to this in order to give you access to check it.

//Code in Open Event of Main Window
if mServiceBusTimer = Nil then
mServiceBusTimer = new eOrderCommunication.ServiceBusTimer
end if
mServiceBusTimer.Period = 1
mServiceBusTimer.Mode = Timer.ModeMultiple
mServiceBusTimer.Enabled = true
mServiceBusTimer.Reset()

The Timer calls the code below. I have changed the links that i Really use.

Dim lvUrlSb as String
Dim lb as Boolean = GetConfigValue(“SbUrl”,lvUrlSb)
lb = GetConfigValue(“SbQueue”,lvQueueName)

Dim sock1 as new eOrderCommunication.eOrderPingServerNew
Dim lvS as String = "Basic "+EncodeBase64(eOrderCommunication.eOrderUsername+":"+eOrderCommunication.eOrderPassword)
sock1.RequestHeader("Authorization")=lvS.ToText
sock1.RequestHeader("User-Agent")="ProfitPOS"
sock1.Send("GET","https://www.testsite.gr/healthcheck.txt")

App.errorLogging(“DEBUG - 3 -”)

if lvUrlSb.len > 0 then
App.errorLogging(“DEBUG - 4 -”)
Dim fItem as FolderItem = GetFolderItem("").Child(“serviceBusSas.txt”)
Dim success as Boolean

Dim rest As New eOrderCommunication.ChilcatRest

if lvUrlSb.right(1)="/" then
  lvUrlSb = lvUrlSb.Left(lvUrlSb.len-1)
end if

Dim queueName As String
queueName = lvQueueName

Dim sbToken As New Chilkat.StringBuilder
success = sbToken.LoadFile(fItem.NativePath,"utf-8")
if Not(success) then
  
end if
success = sbToken.Prepend("SharedAccessSignature ")
success = rest.AddHeader("Authorization",sbToken.GetAsString())


'Dim sock as new eOrderCommunication.eOrderGetMessageQueueOld
'Dim lvUrl as Text = lvUrlSb.ToText+"/"+queueName.ToText+"/messages/head?timeout=30&api-version=2013-08"
'sock.SetRequestHeader("Authorization",sbToken.GetAsString.ToText)
'sock.SendRequest("DELETE",lvUrl)



Dim sock as new eOrderCommunication.eOrderGetMessageQueue
sock.ValidateCertificates = false
Dim lvUrl as Text = lvUrlSb.ToText+"/"+queueName.ToText+"/messages/head?timeout=30&api-version=2013-08"
sock.RequestHeader("Authorization") = sbToken.GetAsString.ToText
sock.Send("DELETE",lvUrl)
App.errorLogging("DEBUG - 5 -")

else
Dim sock1 as new eOrderCommunication.eOrderServiceBusRegisterNew

Dim lvS as String = “Basic “+EncodeBase64(eOrderCommunication.eOrderUsername+”:”+eOrderCommunication.eOrderPassword)
sock1.RequestHeader(“Authorization”) = lvS.ToText
sock1.RequestHeader(“Content-type”) = “application/json”
sock1.ValidateCertificates = false
sock1.ClearRequestHeaders()
sock1.Send(“GET”,eOrderCommunication.eOrderServerIP+“System/FranchiseeManagement/GetQueueConnection”) //DEV
end if

App.errorLogging(“DEBUG - 9 -”)
//Display Main eOrder Counter
Dim th as new thLoadeOrderThread
th.Run()

me.Period = 30000

me.Reset()

If you have the socket “local” scope the the timer event, sure this is gonna cause trouble.

Dim sock1 as new eOrderCommunication.eOrderPingServerNew

Is that a Xojo.Net.HTTPSocket? ?
if so, make it a property of a Window, Module or so. And make SURE the request has had a respone before creating a new instance. It’s best to NOT reuse the sockets (create new instances mysock = New mySocket) when the socket is done.

You now have:

Dim sock as new eOrderCommunication.eOrderGetMessageQueue
sock.ValidateCertificates = false
Dim lvUrl as Text = lvUrlSb.ToText+"/"+queueName.ToText+"/messages/head?timeout=30&api-version=2013-08"
sock.RequestHeader("Authorization") = sbToken.GetAsString.ToText
sock.Send("DELETE",lvUrl)

As soon as the “Timer Action Event” is done, the sockets will become Nil. If there is no response yet, you may get a CRASH, Exception or something else. You MUST keep a reference until you get the Socket Error Event or ContentReceived Event.

your best thing would be to have a Queued socket that handles these requests 1-by-1. But you should code that yourself.

Derk,

Honestly thank you for your help. I really appreciate it.

Yes This is a Xojo.Net.HTTPSocket sublass in a Module.

With my code I always get a response from the socket even if the Timer Action Event is done cause I have logging on my xojo.net.HttpSocket Subclass.
But I will try to make a queue with the requests and make them handled one by one.

I am trying many things on my code in order to find out what’s going on and that’s why I do not answer some times immediately.
I will let you know when i try the 1-1 management.

[quote=471552:@Sebastian Kapellas]Derk,

Honestly thank you for your help. I really appreciate it.

Yes This is a Xojo.Net.HTTPSocket sublass in a Module.

With my code I always get a response from the socket even if the Timer Action Event is done cause I have logging on my xojo.net.HttpSocket Subclass.
But I will try to make a queue with the requests and make them handled one by one.

I am trying many things on my code in order to find out what’s going on and that’s why I do not answer some times immediately.
I will let you know when i try the 1-1 management.[/quote]

In that code you make a “local” instance in the timer event?
Again make that a global or object scope property.

Window.mySocket As eOrderCommunication.eOrderPingServerNew

And keep it alive atleast untill it’s got a response back.
I’m not sure what you mean bu having logging on, do you mean system.debuglog() ?

You have a 80% probability it will work normally when using the latest release (If not try the latest release with URLConnection). Perhaps download 2019R3 and try (you can without a license) see if that fixes it.

Your timer is modeMultiple with a 1 millisecond timeout meaning it’s getting called 1000 times per second. That can’t be good…?

The code you’ve posted doesn’t seem to show this but you might have tested it in the past, have you error logged directly either side of the .Send to make 100% sure its that line that is causing the delay?

How are you testing this loss of connection, pulling the ethernet out / disconnecting via software / trying to resolve a bogus domain name or another method?

On a side note, what would happen to your app if connection was lost between your “connection check” and the “actual request”?

If your answer to this is “carry on gracefully handling that error”, then is there a need to check for connection in the first place?

If your answer to this is “a real problem and a crash/data loss”, then this is something that needs to be thought about :slight_smile:

That small demo project would be helpful when you get a free moment :slight_smile: