这是一个有趣的问题,我还没有能够解决。Delphi Indy IdTcpClient读操作返回截断数据为一个特定的请求
我在写一个客户端,它可以通过Internet与服务器进行通信。我在Indy 10中使用RAD Studio 2007原生个性使用TIdTcpClient Internet Direct(Indy)组件。
要从服务器获取数据,我使用端口443上的SSL发出HTTP请求,其中我的请求详细信息包含在HTTP消息主体中。到现在为止还挺好。代码的作用就像魅力一样,只有一个例外。
我提交的一个请求应该从服务器产生一个约336 KB的响应(HTTP响应头包含Content-Length:344795)。问题是我只得到320KB。 XML中的响应显然在XML元素的中间被截断。
值得一提的是,XML是简单的文本。没有可以解释截断的特殊字符。我的TIdTcpClient组件简单地报告说,在收到部分响应后,服务器优雅地关闭了连接(这是每个响应预期完成的方式,即使那些未被截断的,所以这不是问题)。
我可以对同一台服务器进行几乎相同的调用,其中响应也超过几K字节,并且所有这些工作都很好。一个请求返回大约850 KB,另一个返回大约300 KB,依此类推。
总之,我遇到这个问题只与一个特定的请求。所有其他请求(其中有很多请求都会收到完整的响应)。
我已经跟服务的创建者交谈过,并提供了我的请求的示例。他报告说请求是正确的。他还告诉我,当他向我的服务器发出同样的请求时,他会得到完整的回复。
我不知所措。无论是服务的创建者都是错误的,实际上在响应方面存在问题,或者我的请求有一些特殊之处。
有没有解决方案,我错过了?请注意,我还使用了许多其他读取机制(ReadString,ReadStrings,ReadBytes等),并且都产生了相同的结果,在320KB标记处截断了此特定响应。
该代码可能不相关,但我仍然会将其包含在内。抱歉,我不能包含XML请求,因为它包含专有信息。 (ReadTimeout被设定为20秒,但在约1秒的请求返回,所以它不是超时问题。)
function TClient.GetResponse(PayloadCDS: TClientDataSet): String; var s: String; begin try try s := GetBody(PayloadCDS); IdTcpClient1.Host := Host; IdTcpClient1.Port := StrToInt(Port); IdTcpClient1.ReadTimeout := ReadTimeout; IdTcpClient1.Connect; IdTcpClient1.IOHandler.LargeStream := True; //IdTcpClient1.IOHandler.RecvBufferSize := 2000000; IdTcpClient1.IOHandler.Write(s); Result := IdTcpClient1.IOHandler.AllData; except on E: EIdConnClosedGracefully do begin //eat the exception end; on e: Exception do begin raise; end; end; finally if IdTcpClient1.Connected then IdTcpClient1.Disconnect; end; end;
TIdHTTP支持SSL,与TIdTCPClient一样 - 通过在连接之前分配启用SSL的IOHandler。你真的应该使用TIdHTTP组件来处理HTTP流量。这就是为什么它首先存在。 – 2009-08-18 20:06:49
另外,在当前的Indy 10版本中,SSLOptions.Method属性的默认值不是sslvSSLv2,而是sslvTLSv1。不过,将方法设置为sslvSSLv23会清除一些错误确实有意义。当Method被设置为除sslvSSLv23以外的任何其他方时,* *必须*在其最后使用该特定的SSL版本,否则SSL握手将失败。另一方面,sslvSSLv23更像是一个全面通配符,它支持SSLv2到TLSv1的所有SSL版本,并允许双方协商兼容的SSL版本。 – 2009-08-18 20:09:45