Reputation: 335
I am trying to use a Client-Server Datasnap based architecture. The client is inside an Android App that connects by Wifi with the Server Program which runs in a PC.
This are the server and client features:
Server Methods
TSQLConnection
Server Container
TDSServer
TDSTCPServerTransport
Main
TSQLConnection
The function:
function TFrm_Principal.GetServerMethods1Client: TServerMethods1Client;
begin
Conexion.Close;
Conexion.Open;
if FServerMethods1Client = nil then
begin
FServerMethods1Client := TServerMethods1Client.Create
(Conexion.DBXConnection, FInstanceOwner);
end;
result := FServerMethods1Client;
end;
ClientClasses
The function:
function TServerMethods2Client.validaEstado(factura: string): Boolean;
begin
try
if FvalidaEstadoCommand = nil then
begin
FvalidaEstadoCommand := FDBXConnection.CreateCommand;
FvalidaEstadoCommand.CommandType := TDBXCommandTypes.DSServerMethod;
FvalidaEstadoCommand.Text := 'TServerMethods1.validaEstado';
FvalidaEstadoCommand.Prepare;
end;
FvalidaEstadoCommand.CommandTimeout := 3;
FvalidaEstadoCommand.Parameters[0].Value.SetWideString(factura);
FvalidaEstadoCommand.ExecuteUpdate;
Result := FvalidaEstadoCommand.Parameters[1].Value.GetBoolean;
except
on e: Exception do
begin
controlarError;
end;
end;
end;
Everything works very fine and fast, but when the Tablet looses Wifi connection with the Server, it hangs for more than the timeout time assigned in the different properties. Some times I wait for 30 or 40 seconds and there is no response. If I go closer to the network router, sometimes it recovers the flow, but if I stay away, the app finally crashes. The question is: why would it hang if there are timeouts which should make the app respond with a "could not connect to the network on time" or "timeout error" instead of just hanging with out any posibility for the user than waiting or restarting the app?
Upvotes: 3
Views: 4054
Reputation: 9481
I haven't used Firebird yet, but have used TSQLConnection
with DataSnap. I assume Firebird uses the same communication libraries as TSQLConnection
. If so, then:
The underlying calls are handed off to Windows (i.e., WinSock) and there is no way that I have found to check to see if the connection is still intact.
I wrote a simple DataSnap server-side function called CheckCon()
, which does nothing besides give the client app something to call on the server to see if the communication channel is still connected. I put the client-side call to CheckCon()
in a try...except
block so I could trap the error and auto-reconnect when an EIdSocketError
is raised.
The user gets auto-reconnected, which is helpful, but the user still has to wait 30 seconds for the Windows WinSock to timeout before it returns a socket error and the auto-reconnect code executes.
This old thread has an explanation from Remy Lebeau about a similar topic, and since DataSnap uses Indy, I think it applies here too:
You won't be able to [check if the client is still connected to the server] in a timely manner. Indy uses blocking sockets, and blocking sockets simply are not designed to detect abnormal disconnects quickly. When an abnormal disconnect occurs, the underlying socket library (WinSock on Windows, Libc on Linux, etc) will not know that the socket is lost until the library times out internally and then invalidates the socket. Until that happens, there is no way for Indy to know whether the socket is actually connected or not, because the library itself does not know.
Upvotes: 1