我正在使用 Internet Direct TIdTCPClient 组件与远程服务进行通信,以检索通常约为 5k 大小的消息。在典型的操作中,我会向服务发送大约 400 个请求,每个请求大约需要 1 秒才能完成。大多数时候一切正常。但是,大约有 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;
Run Code Online (Sandbox Code Playgroud)
使用 IOHandler.AllData 读取数据非常方便,但我无法在失败后检索任何数据(AllData 返回空字符串)。我在失败后测试了 IOHandler.InputBufferIsEmpty,它返回 True。
我还尝试了其他方法来读取数据,例如 IOHandler.ReadStream(这产生了与读取 AllData 相同的结果)。我还使用了 IOHandler.ReadBytes 和 IOHandler.ReadByte(与 IOHandler.CheckForDataOnSource 结合使用)。没有任何效果。
部分数据传输我错了吗?如果是这样,为什么我会在失败前看到一致的 189.nnnn 秒延迟。
如果部分数据传输是可能的,我应该采取什么方法来捕获失败前接收到的每个字节数据。
我在这个项目和 Indy 10 中使用 Delphi 2009,但我认为该版本与它没有任何关系。我认为这不是 Indy 问题。
编辑:我已经使用 WireShark 检查了我的 Indy 客户端和服务器之间的通信。当这些故障之一发生时,在发送我的请求后,服务器发送了两个 [ACK] 数据包,然后静默超过 189 秒。在那段延迟之后,响应包括 [FIN, PSH, ACK] 但没有应用程序数据。
当通信正常时,服务器响应我的请求返回的两个ACK包后面跟着一个应用程序数据包。
编辑:已将问题报告给 Web 服务的发布者,正在等待回复。
编辑:好的,Web 服务的发布者已响应。他们承认自己的问题并解决了其中的一些问题。我们不再出现超时。大多数响应在大约 2 秒内收到,少数响应时间稍长。发布商正在努力解决其余问题。
感谢大家的投入。
您需要运行 Fiddler2 并观察流量。它将自身作为代理插入并嗅探使用 WinInet 堆栈的所有信息。然后您就知道是否收到了任何数据,以及您正在发送和接收的数据。 http://www.fiddler2.com/fiddler2/