简体   繁体   中英

How to make indy server and client listen for data on separate thread in c++ not Delphi

I am using c++ builder XE8, and I am just a beginner. I don't know anything about Delphi. To listen for incoming data on server and client both end, I inserted Thread Object from Flie->New->Other->C++ builder Files (as I saw in a video demo of threading), and named it TSocketThreard.

On the client end I assign the client socket to a TIdIOHandlerSocket var (fsock) and used the following code to listen continuously for imcoming data. len is int, s is String var and lbox is a 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);
        }

    }
}

I tried to start it from client's onConnect event and from a button(I use to connect the client to server) also. But both times its got freeze.

On the server end I tried to OnExecute event on the same way. I mean, at first assigned socket to a var, put the code like above on a thread's(which I inserted like before) execute method, and started the thread's start() method from onExecute event.For the server I want to make it work on asynchronous mode (to handle at least few hundreds clients).

I can feel I am doing it the wrong way, but its really hard to find a good example in c++. Please some one show me the right way.

Indy servers are already multi-threaded, you don't need to create your own reading threads. The TIdTCPServer::OnExecute event runs in a thread, and each client has its own thread. Just use the socket that the event gives you, don't use your own variable.

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

On the client side, your reading thread is doing things that are not thread-safe, which can lead to UI freezing, amongst other problems. Try something more like this instead:

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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM