我正在尝试使用基于客户端-服务器Datasnap的体系结构。客户端位于Android应用程序内部,该应用程序通过Wifi与PC上运行的服务器程序连接。
这是服务器和客户端功能:
服务器方法
TSQLConnection
服务器容器
TDSServer
TDSTCPServerTransport
Main
TSQLConnection
功能:
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
功能:
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;
一切正常且快速,但是当Tablet断开与服务器的Wifi连接时,其挂起的时间超过了在不同属性中指定的超时时间。有时我等待30或40秒,但没有响应。如果我靠近网络路由器,有时它可以恢复流量,但是如果我不在的话,该应用程序最终将崩溃。问题是:如果超时会使应用程序响应“无法及时连接到网络”或“超时错误”,为什么会挂起,而不是仅仅挂断用户等待或重启的可能性,为什么会挂起?该应用程序?
我还没有使用Firebird,但已将TSQLConnection
与DataSnap一起使用。我假设Firebird使用与TSQLConnection
相同的通信库。如果是这样,则:
基础调用已移交给Windows(即WinSock),并且有一种[[no我发现可以检查连接是否仍然完好的方法。
我编写了一个简单的DataSnap服务器端函数CheckCon()
,该函数除了为客户端应用程序提供一些在服务器上调用的功能以查看通信通道是否仍处于连接状态之外,什么也不做。我将客户端调用放在CheckCon()
块中的try...except
上,这样我可以捕获错误并在引发EIdSocketError
时自动重新连接。用户会自动重新连接,这很有帮助,但是用户仍然需要等待30秒以使Windows WinSock超时,然后它会返回套接字错误并执行自动重新连接代码。
[This old thread从Remy Lebeau那里得到了关于类似主题的解释,并且由于DataSnap使用Indy,所以我认为它也适用于此:]]
您将无法[检查客户端是否仍连接到服务器]。 Indy使用阻塞套接字和阻塞插座根本无法检测异常断开很快。发生异常断开连接时,基础套接字库(Windows上的WinSock,Linux上的Libc等)不会知道套接字丢失,直到库内部超时,然后使套接字无效。在那之前,印地是不可能的知道插座是否实际连接,因为库本身不知道。