如何使用 Indy TIdTCPClient 处理 MaxLineLengthExceeded

How To Deal With MaxLineLengthExceeded With Indy TIdTCPClient

我是 Indy 的新手,使用 CBuilder XE4 附带的任何版本。这是非常简单的代码,在我阅读的内容超过 16K 限制之前可以正常工作....

String Ttcp_mgr::send(String data)
{
  tcpClient->Socket->WriteLn(data); 
  return tcpClient->Socket->ReadLn();
}

服务器未使用 indy,没有长度 header,双向 json 被 \r\n 终止。阻止读取很好,我的应用程序在收到响应之前无事可做,而且它很快就会到来。但在少数情况下,返回的数据量可能是几个字节或 100K。通常长度将小于 500 字节。

我看过 IOHandler,但我不知道如何将它应用到我正在做的事情中,甚至不确定它是否是我需要的。正如您可能会说的那样,我没有在可能没有任何区别的表单上使用该组件。

TIdIOHandler::ReadLn() 有一个可选的 AMaxLineLength 输入参数。如果您不为其指定值,则使用 TIdIOHandler::MaxLineLength 属性,默认设置为 16K。 TIdIOHandler::MaxLineAction 属性 指定如果 ReadLn() 实际达到最大行长度时会发生什么。

如果 MaxLineActionmaException(默认值),则会引发 EIdReadLnMaxLineLengthExceeded 异常。

如果 MaxLineActionmaSplit,则 TIdIOHandler::ReadLnSplit 属性 设置为 true 并且 ReadLn() returns 可以。您必须再次调用 ReadLn() 才能读取当前行的更多数据。如果它对非 ASCII 字符使用多字节编码,例如 UTF-8(JSON 的默认编码),这最终可能会错误地截断数据,因此我不推荐这种方法。

在你的情况下,你应该:

  1. 设置 TIdIOHandler::MaxLineLength 属性 为 MaxInt:

    // TIdTCPClient::OnConnected event handler...
    void __fastcall Ttcp_mgr::tcpCllientConnected(TObject *Sender)
    {
        tcpClient->IOHandler->MaxLineLength = MaxInt;
    }
    
  2. MaxInt作为参数传递给TIdIOHandler::ReadLn()

    String Ttcp_mgr::send(String data)
    {
        tcpClient->Socket->WriteLn(data); 
        return tcpClient->Socket->ReadLn(EOL, IdTimeoutDefault, MaxInt);
    }
    

所有Delphi用户:设置IOHandler.MaxLineLength到"MaxInt"必须在开始连接后完成,否则会出现内存错误。

IdPOP31.Connect;
IdPOP31.IOHandler.MaxLineLength := MaxInt;

其他一切如上,解决了 Delphi.

解析过长邮件的问题