德尔福& Datasnap - 连接超时,通信超时或在没有服务器响应时避免客户端应用程序挂起的方法

时间:2016-02-06 20:49:47

标签: android delphi firebird datasnap

我正在尝试使用基于Client-Server Datasnap的架构。客户端位于Android应用程序中,通过Wifi连接到在PC中运行的服务器程序。

这是服务器和客户端功能:

服务器端:

服务器方法

设为TSQLConnection

  • 司机:Firebird。
  • KeepConnection:true。

服务器容器

TDSServer

  • Queuesize:100
  • ChannelresponseTimeout:3000

TDSTCPServerTransport

  • BufferKBSize:32
  • KeepAliveEnablement:kaDisabled
  • MaxThreads:30
  • PoolSize:10
  • 港口:211

客户端

主要

设为TSQLConnection

  • 司机:Datasnap
  • ConnectTimeout:2000
  • CommunicationTimeOut:5000
  • DBXConnection构造函数:

功能:

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;

一切都运行得非常好而且速度很快,但是当平板电脑失去与服务器的Wifi连接时,它会挂起超过在不同属性中指定的超时时间。有时候我会等30或40秒而没有回应。如果我靠近网络路由器,有时它会恢复流量,但如果我离开,应用程序最终会崩溃。 问题是:如果有超时应该让应用程序响应“无法及时连接到网络”,为什么会挂起?或"超时错误"与等待或重新启动应用程序相比,而不仅仅是为用户提供任何可能性?

1 个答案:

答案 0 :(得分:0)

我还没有使用Firebird,但是将TSQLConnection与DataSnap一起使用了。我假设Firebird使用与TSQLConnection相同的通信库。如果是这样,那么:

基础调用已移交给Windows(即WinSock),我发现的方法来检查连接是否仍然完好。

我编写了一个名为CheckCon()的简单DataSnap服务器端函数,除了为客户端应用程序提供一些在服务器上调用的功能以查看通信通道是否仍处于连接状态之外,没有任何其他作用。我将客户端调用CheckCon()放在try...except块中,这样我可以捕获错误并在引发EIdSocketError时自动重新连接。

用户可以自动重新连接,这很有帮助,但是用户仍然需要等待30秒以使Windows WinSock超时,然后再返回套接字错误并执行自动重新连接代码。

This old thread从Remy Lebeau那里得到了一个类似主题的解释,并且由于DataSnap使用Indy,所以我认为它也适用于此:

您将无法[检查客户端是否仍连接到 服务器]。 Indy使用阻塞套接字和阻塞 插座根本无法检测异常断开 很快。当发生异常断开连接时,基础套接字 库(Windows上的WinSock,Linux上的Libc等)不会知道 套接字丢失,直到库内部超时,然后 使套接字无效。在那之前,印地是不可能的 知道插座是否实际连接,因为 库本身不知道。