【问题标题】:Reading delimited packets with Indy TIdTCPServer in C++Builder在 C++Builder 中使用 Indy TIdTCPServer 读取分隔数据包
【发布时间】:2020-11-26 05:45:34
【问题描述】:

我有一个微处理器设备想要连接到 TCP 服务器,然后在每次输入状态发生变化时发送一个令牌。令牌采用"AS9=0;" 的形式,没有CRLF。每个令牌都在一个长度为 6 的数据包中发送。为了使我的项目正常工作,我希望允许连接打开、接收数据并使用它,而无需等待另一个打包或关闭连接。

C++Builder 附带的套接字组件集是 Indy 10。它代表了惊人的工作量。但是,所有这些工作都在 Pascal 中,对我没有多大用处。可以说文档很困难。理想情况下,我想逐包读取数据。我可以确定没有办法做到这一点。我试过AllData() 方法。虽然它可以工作,但它会等到连接关闭才能读出数据。这对我不可用。我也尝试过ReadLn() 方法。一旦遇到LF,它就会读出数据。它也没有用,因为我的数据不包含LFs。

到目前为止,我的代码如下所示:

void __fastcall TForm1::IdTCPServer1Execute(TIdContext *AContext)
{
    UnicodeString mystring;
    RichEdit1->Lines->Add(" * ");
    mystring = AContext->Connection->IOHandler->AllData();
    RichEdit1->Lines->Add(mystring + " *** ");
}
//-----------------------------------
void __fastcall TForm1::IdTCPServer1Disconnect(TIdContext *AContext)
{
    RichEdit1->Lines->Add("Disconnected. . .  \r\n");
}
//--------------------------------------
void __fastcall TForm1::IdTCPServer1Connect(TIdContext *AContext)
{
    RichEdit1->Lines->Add("Connected. . .  \r\n");
}
//---------------------------------------

正如我所提到的,上面的代码将显示所有内容,但只有在连接关闭时才会显示。鉴于所有这些,我有两个问题。首先,如何在数据包进来后立即获取数据?其次,对于ReadLn(),如何将行分隔符从LF 更改为";"

【问题讨论】:

    标签: c++builder indy


    【解决方案1】:

    如果您查看TIdIOHandler::ReadLn() 的声明,您会看到它有一个可选的ATerminator 参数:

    String __fastcall ReadLn(_di_IIdTextEncoding AByteEncoding  = NULL);
    
    String __fastcall ReadLn(String ATerminator, _di_IIdTextEncoding AByteEncoding);
    
    String __fastcall ReadLn(String ATerminator, int ATimeout = IdTimeoutDefault, int AMaxLineLength = -1, _di_IIdTextEncoding AByteEncoding = NULL);
    

    如果不指定终止符,则默认为LF(包括CRLF)。您可以根据需要指定不同的终止符,例如:

    void __fastcall TForm1::IdTCPServer1Execute(TIdContext *AContext)
    {
        ...
        String mystring = AContext->Connection->IOHandler->ReadLn(_D(";"));
        ...
    }
    

    另外,TIdTCPServer 是一个多线程组件。它的事件在工作线程的上下文中触发。因此,您必须在访问 UI 控件时与主 UI 线程同步,例如:

    void __fastcall TForm1::AddLine(const String &S)
    {
        #if defined(__clang__)
        TThread::Synchronize(nullptr, [&, this](){ RichEdit1->Lines->Add(S); });
        #else
        struct TAddLineSync
        {
            String Line;
            TAddLineSync(const String &ALine) : Line(ALine) {}
            void __fastcall AddLine() { Form1->RichEdit1->Lines->Add(Line); }
        };
        TAddLineSync sync(S);
        TThread::Synchronize(NULL, &sync.AddLine);
        #endif
    }
    //-----------------------------------
    void __fastcall TForm1::IdTCPServer1Execute(TIdContext *AContext)
    {
        AddLine(_D(" * "));
        String mystring = AContext->Connection->IOHandler->ReadLn(_D(";"));
        AddLine(mystring + _D(" *** "));
    }
    //-----------------------------------
    void __fastcall TForm1::IdTCPServer1Disconnect(TIdContext *AContext)
    {
        AddLine(_D("Disconnected. . .  \r\n"));
    }
    //--------------------------------------
    void __fastcall TForm1::IdTCPServer1Connect(TIdContext *AContext)
    {
        AddLine(_D("Connected. . .  \r\n"));
    }
    //---------------------------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2023-01-16
      • 2012-07-12
      • 1970-01-01
      相关资源
      最近更新 更多