时间:2010-07-25 10:01:33

标签: delphi delphi-2010 indy indy10

1 个答案:

答案 0 :(得分:6)

问题出在您的代码中,而不是ReadStream()。它按照设计行事。

它接受3个输入参数:

procedure ReadStream(AStream: TStream; AByteCount: TIdStreamSize = -1; AReadUntilDisconnect: Boolean = False); virtual;

您只为第一个参数提供值,因此其他两个参数使用默认值。

AByteCount参数设置为-1且AReadUntilDisconnect参数设置为False时,ReadStream()设计为假设接收的前4个字节(或8个字节,如果IOHandler.LargeStream属性设置为True)是发送数据的长度,之后是实际数据。这就是为ReadStream()调用ReadLongInt()的原因。这不仅会告诉ReadStream()何时停止读取,而且还允许ReadStream()预先调整目标TStream的大小,以便在接收数据之前更好地进行内存管理。

如果客户端实际上没有在其数据之前发送4字节(或8字节)长度值,那么ReadStream()仍然会将实际数据的起始字节解释为长度。这通常(但并非总是如此,取决于数据)导致ReadLongInt()(或ReadInt64())返回一个大整数值,这会导致ReadStream()期望大量数据将永远不会实际到达,从而无限制地阻止读取(或者直到发生超时,如果IOHandler.ReadTimeout属性设置为非无限超时)。

为了有效地使用ReadStream(),它需要知道何时停止阅读,或者通过提前告知预期有多少数据(即:AByteCount >= 0),或者要求发送者发送数据后断开连接(即:AReadUtilDisconnect = True)。 {(1}}和AByteCount = -1的组合是一种特殊情况,当长度直接在流媒体中编码时。当发件人调用AReadUtilDisconnect = False并将IOHandler.Write(TStream)参数设置为True(默认情况下为False)时,主要使用(但不限于此)。

在处理非文本数据时,尽可能在实际数据之前发送数据长度始终是个好主意。它优化了阅读操作。

ReadStream()的不同参数组合符合以下逻辑:

  1. AByteCount = -1,AReadUtilDisconnect = False:读取4/8字节,解释为长度,然后继续读取,直到收到该长度。

  2. AByteCount< -1,AReadUtilDisconnect = False:假设AReadUntilDisconnect为True并继续读取,直到断开连接。

  3. AByteCount> -1,AReadUtilDisconnect = False:预先调整目标TStream的大小并继续读取,直到收到AByteCount字节数。

  4. AByteCount< = -1,AReadUtilDisconnect = True:继续阅读,直到断开连接。

  5. AByteCount> -1,AReadUtilDisconnect = True:预先调整目标TStream的大小并继续读取,直到断开连接。

  6. 根据客户端实际发送到服务器的数据类型,AWriteByteCount可能不是读取该数据的最佳选择。 IOHandler有许多不同类型的阅读方法。例如,如果客户端正在发送带分隔符的文本(特别是如果它与ReadStream()一起发送),那么IOHandler.WriteLn()是更好的选择。