我特别想知道发生故障时究竟发生了什么,以便我可以将我的证据带给服务的发布者.首先,失败是不可重复的.如果我重新发送一个失败的请求,它的可能性非常高(可能是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/