【问题标题】:How to make indy server and client listen for data on separate thread in c++ not Delphi如何使 indy 服务器和客户端在 C++ 中的单独线程上侦听数据而不是 Delphi
【发布时间】:2015-10-30 13:34:09
【问题描述】:

我正在使用 c++ builder XE8,我只是一个初学者。我对德尔福一无所知。为了监听服务器端和客户端的传入数据,我从Flie->New->Other->C++ builder Files 插入了Thread Object(正如我在线程视频演示中看到的那样),并将其命名为 TSocketThreard。

在客户端,我将客户端套接字分配给 TIdIOHandlerSocket var (fsock),并使用以下代码连续侦听传入数据。 len 是 int,s 是 String var,lbox 是 TListBox。

void __fastcall TSocketThread::Execute()
{
    FreeOnTerminate = True;
    while(1){
        if (Form1->fsock != NULL && Form1->fsock->Connected()) {
            if(Form1->fsock->CheckForDataOnSource(10))
                Form1->len = Form1->fsock->ReadLongInt();
                Form1->s = Form1->fsock->ReadString(Form1->len);
                Form1->lbox->Items->Add(Form1->s);
        }

    }
}

我也尝试从客户端的 onConnect 事件和按钮(我用来将客户端连接到服务器)启动它。但两次都被冻结了。

在服务器端,我尝试以相同的方式执行 OnExecute 事件。我的意思是,首先将套接字分配给一个var,将上面的代码放在线程的(我之前插入的)执行方法上,然后从onExecute事件启动线程的start()方法。对于服务器,我想让它工作在异步模式下(处理至少几百个客户端)。

我觉得我做错了,但在 c++ 中很难找到一个好的例子。请有人告诉我正确的方法。

【问题讨论】:

    标签: multithreading sockets c++builder indy10


    【解决方案1】:

    Indy 服务器已经是多线程的,您不需要创建自己的阅读线程。 TIdTCPServer::OnExecute 事件在一个线程中运行,每个客户端都有自己的线程。只使用事件给你的套接字,不要使用你自己的变量。

    void __fastcall TMyServerForm::IdTCPServer1Execute(TIdContext *AContext)
    {
        // use AContext->Connection->IOHandler as needed...
    }
    

    在客户端,您的阅读线程正在执行非线程安全的操作,这可能会导致 UI 冻结等问题。尝试更多类似的方法:

    class TSocketThread : public TThread
    {
    private:
        TIdIOHandler *fIOHandler;
        String fString;
        void __fastcall UpdateListBox();
    protected:
        virtual void __fastcall Execute();
    public
        __fastcall TSocketThread(TIdIOHandler *AIOHandler);
    };
    
    __fastcall TSocketThread::TSocketThread(TIdIOHandler *AIOHandler)
        : TThread(false), fIOHandler(AIOHandler)
    {
    }
    
    void __fastcall TSocketThread::Execute()
    {
        while (!Terminated)
        {
            int len = fIOHandler->ReadLongInt();
            fString = fIOHandler->ReadString(len);
            Synchronize(&UpdateListBox);
        }
    }
    
    void __fastcall TSocketThread::UpdateListBox()
    {
        Form1->lbox->Items->Add(fString);
    }
    

    TSocketThread *Thread = NULL;
    
    void __fastcall TMyClientForm::IdTCPClient1Connected(TObject *Sender)
    {
        Thread = new TSocketThread(IdTCPClient1->IOHandler);
    }
    
    void __fastcall TMyClientForm::IdTCPClient1Disconnected(TObject *Sender)
    {
        if (!Thread) return;
        Thread->Terminate();
        if (!IsCurrentThread(Thread))
        {
            Thread->WaitFor();
            delete Thread;
            Thread = NULL;
        }
    }
    

    【讨论】:

    • 非常非常非常感谢@Remy Sir,我没能及时回复,因为我有点不舒服。我现在就试试,先生,我真的很高兴你。我只有一个关于 indy 服务器的问题,如果它已经是多线程的,来自一个客户端的响应是否会中断/暂停另一个客户端的响应处理,如果它们同时到达服务器?跨度>
    • 先生,当我尝试您的代码时,还有一件事显示 unknown type name 'TIdIOHandler' 错误。我是否必须为此包含任何额外的头文件?
    • 哦,我已经找到答案了#include <IdTCPConnection.hpp>。
    • TIdIOHandler 在IdIOHandler.hpp 中声明,即#include'd by IdTCPConnection.hpp。大多数 Indy 类/组件都是在它们自己的单元中实现的。
    • 在访问 Label 和 ListBox 控件时,您没有与主 UI 线程同步。
    猜你喜欢
    • 2012-12-24
    • 2019-04-13
    • 2012-04-11
    • 1970-01-01
    • 2015-01-28
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    相关资源
    最近更新 更多