日安。我使用TIdTCPClient组件向服务器发送请求并读取响应。我知道某些请求的响应大小,但不知道其他请求的响应大小。
当我知道响应的大小时,我的数据读取代码如下所示:
IdTCPClient1->Socket->Write(requestBuffer);
IdTCPClient1->Socket->ReadBytes(answerBuffer, expectSize);当我不知道响应的大小时,我会使用以下代码:
IdTCPClient1->Socket->Write(requestBuffer);
IdTCPClient1->Socket->ReadBytes(answerBuffer, -1);在这两种情况下,我都遇到了问题。在第一种情况下,如果服务器没有返回所有数据(小于expectSize),那么IdTCPClient1将等待ReadTimeout完成,但是answerBuffer中将根本没有数据(即使服务器发送了一些数据)。这就是TIdTCPClient背后的逻辑吗?对不对?
在第二种情况下,ReadTimeout根本不起作用。也就是说,ReadBytes函数立即结束,不向answerBuffer写入任何内容,或者写入来自服务器的几个字节。但是,我认为由于这个函数在本例中不知道要读取的字节数,它必须等待ReadTimeout并读取在此期间到来的字节。在这个实验中,我在写入和读取之间插入了睡眠(500),然后我读取了所有到达的数据。我可以请您回答为什么会发生这种情况吗?
发布于 2019-12-18 03:36:12
日安。我使用TIdTCPClient组件向服务器发送请求并读取响应。我知道某些请求的响应大小,但不知道其他请求的响应大小。
为什么你不知道所有响应的大小?您的协议实际上是什么样子的?TCP是字节流,每个消息必须以这样的方式成帧,以便接收者能够知道每个消息的开始和结束位置,以便正确地读取消息并保持流的完整性。因此,消息必须在其有效负载中包含其大小,或者在消息之间进行唯一分隔。那么,在你的情况下是哪种情况呢?这听起来不像是你在处理这两种可能性。
当我不知道响应的大小时,我使用以下代码:
IdTCPClient1->Socket->Write(requestBuffer);IdTCPClient1->Socket->ReadBytes(answerBuffer,-1);
当您将AByteCount设置为-1时,这将告诉ReadBytes()返回IOHandler的InputBuffer中当前可用的任何字节。如果InputBuffer为空,ReadBytes()将等待至少1个字节到达,然后它将返回实际接收到InputBuffer中的任何字节,直到IOHandler的<代码>D13指定的最大值。因此,可能仍需要多次读取才能完整读取整个消息。
通常,在处理实际协议时,不应将AByteCount设置为-1。只有在代理/流式传输任意数据时才适合使用,在这种情况下,用户并不关心实际字节是什么。任何其他用途都需要了解协议的详细信息,即消息是如何成帧的。
在第一种情况下,如果服务器没有返回所有数据(小于expectSize),那么IdTCPClient1将等待ReadTimeout完成,但是answerBuffer中将根本没有数据(即使服务器发送了一些数据)。这就是TIdTCPClient背后的逻辑吗?对不对?
是。当AByteCount > 0时,ReadBytes()等待指定的字节数在InputBuffer中可用,然后将这些字节提取到输出TIdBytes中。除非所有请求的字节都可用,否则不会修改您的answerBuffer。如果ReadTimeout过期,则会引发EIdReadTimeout异常,并且您的answerBuffer保持不变。
如果这不是您想要的行为,那么考虑使用ReadStream()而不是ReadBytes(),使用TIdMemoryBufferStream或TBytesStream进行读取。
在第二种情况下,ReadTimeout根本不起作用。也就是说,ReadBytes函数会立即结束,并且不会向answerBuffer写入任何内容。
我从来没有听说过ReadBytes()不等待ReadTimeout。只有当InputBuffer中没有可用的字节,并且ReadTimeout设置为某个非常小的值(如0毫秒)时,才会发生您所描述的情况。
从服务器写入
或几个字节。
这是一个非常合理的结果,因为您要求ReadBytes()在1..RecvBufferSize之间读取任意数量的字节,如果超时,则不读取任何字节。
然而,我预期由于这个函数在本例中不知道要读取的字节数,它必须等待ReadTimeout并读取在此期间到来的字节。
是的,这就是它应该如何工作的。以及它一直是如何工作的。因此,我建议您在运行时调试到ReadBytes()中,并找出它不能按照预期的方式工作的原因。此外,请确保您使用的是最新版本的Indy (或者至少是最近几年的版本)。
发布于 2019-12-18 13:44:03
为什么您不知道所有响应的大小?
因为,事实上,我正在做一个电子设备的调查。此设备有自己的网络IP地址和端口。因此,设备可以根据其状态以不同的方式响应相同的请求。严格地说,某些查询可以有两个答案,并且它们的长度不同。在这些情况下,当读取时,我指定AByteCount = -1来读取任何设备响应。
我从来没有听说过ReadBytes()不等待ReadTimeout。
你是对的!我错了。当指定AByteCount =-1时,我得到一个字节。正如您所说的,如果至少有一个字节到达,它将返回并结束ReadBytes()。
此外,请确保您使用的是最新版本的
(或者至少是最近几年的一个版本)。
我正在使用C++ Builder10.3社区版,Indy10.6.2.5366版。
https://stackoverflow.com/questions/59369213
复制相似问题