当前位置 : 主页 > 编程语言 > delphi >

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

来源:互联网 收集:自由互联 发布时间:2021-06-23
我正在使用Internet Direct TIdTCPClient组件与远程服务进行通信,以检索通常大小约为5k的消息.在典型操作期间,我将向服务发送大约400个请求,每个请求大约需要1秒钟才能完成.大多数时候一切
我正在使用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,但我不认为该版本与它有任何关系.我不认为这是一个印第安问题.

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

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

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

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

谢谢大家的意见.

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