Indy TIdTCPClient组件偶尔不会超时并且不接收任何数据

时间:2011-06-28 13:54:02

标签: delphi tcp indy

我正在使用Internet Direct TIdTCPClient组件与远程服务进行通信,以检索通常大小约为5k的邮件。在典型操作期间,我将向服务发送大约400个请求,每个请求大约需要1秒钟才能完成。大多数时候一切都很完美。但是,大约百分之一的时间请求需要189秒,而我根本没有收到任何数据。为了便于讨论,我将其称为失败。

我特别想知道发生故障时到底发生了什么,以便我可以将我的证据带给服务的发布者。首先,失败是不可重复的。如果我重新发送失败的请求,那么它的可能性很高(可能是99%)。

我还捕获了发生故障时发送的请求,因此我能够确认请求是否格式良好。

我假设在失败期间我得到了一些数据,而不是全部。这就是原因。我的IdTCPClient有30秒超时(我甚至将它设置为5秒,但这没有什么区别)。当故障发生时,它总是在189秒(加上约500毫秒)后失败。

因此,我认为在故障期间我的组件正在接收涓流的数据,这就是我的客户端没有超时的原因。并且,我假设在服务中发生断开连接,因为我的超时值都没有设置为189秒。另一方面,读取IOHandler.AllData不会引发异常(甚至不会引发EIdConnClosedGracefully异常)。我是否正确地解释了这些证据?

我想要做的是在服务终止连接之前确认我正在获取一些数据,而不是全部数据。此外,我想知道部分数据是什么样的,因为我相信它可以帮助确定失败的根源。

目前,我的请求类似于以下内容:

//ExceptionName is a temporary global variable
//that I am using while trying to solve this issue
ExceptionName = 'no exception';
try
  s := GetRequest(id);
  IdTcpClient1.Host := Host;
  IdTcpClient1.Port := StrToInt(Port);
  IdTcpClient1.ReadTimeout := ReadTimeout;
  try
    IdTcpClient1.Connect;
  except
    on e: exception do
    begin
      ExceptionName := e.ClassName;
      raise EConnectionFailure.Create('Connection refused: ' + e.Message)
    end;
  end;
  IdTcpClient1.IOHandler.Writeln(s);
  try
    Result := IdTcpClient1.IOHandler.AllData;
  except
    on E: EIdConnClosedGracefully do
    begin
       ExceptionName := e.ClassName;
       //eat this exception
    end;
    on e: Exception do
    begin
       ExceptionName := e.ClassName;
      raise;
    end;
  end;
finally
  if IdTcpClient1.Connected then
    IdTcpClient1.Disconnect;
end;

使用IOHandler.AllData读取数据非常方便,但是我无法在失败后检索任何数据(AllData返回一个空字符串)。我在失败后测试了IOHandler.InputBufferIsEmpty,它返回True。

我还尝试过其他方法来读取数据,例如IOHandler.ReadStream(这会产生与读取AllData相同的结果)。我还使用了IOHandler.ReadBytes和IOHandler.ReadByte(与IOHandler.CheckForDataOnSource一起使用)。没有任何效果。

我对部分数据传输有误吗?如果是这样,为什么我会在失败前看到一致的189.nnnn秒延迟。

如果有可能进行部分数据传输,我应该采取什么方法来捕获失败前收到的每个数据字节。

我正在将Delphi 2009用于此项目和Indy 10,但我不认为该版本与它有任何关系。我不认为这是一个Indy问题。


编辑:我使用WireShark检查了我的Indy客户端和服务器之间的通信。当其中一个故障发生时,在发送我的请求后,服务器发送两个[ACK]数据包,然后静音超过189秒。在该延迟之后,响应包括[FIN,PSH,ACK]但没有应用程序数据。

当通信正常工作时,服务器响应我的请求返回的两个ACK数据包之后是应用程序数据包。


编辑:已向Web服务的发布者报告了该问题,我正在等待回复。


编辑:好的,Web服务的发布者已经回复了。他们承认自己的问题并解决了其中的一些问题。我们不再获得超时。大多数响应在大约2秒内收到,少数响应时间稍长。发布商正在努力解决剩余的问题。

感谢大家的意见。

1 个答案:

答案 0 :(得分:1)

您需要运行Fiddler2并观察流量。它将自身作为代理插入并嗅探使用WinInet堆栈的外观。 然后你知道你是否有任何数据,以及你发送和接收的确切内容。 http://www.fiddler2.com/fiddler2/