如何让 Indy 服务器和客户端在 C++ 中的单独线程上监听数据而不是 Delphi
How to make indy server and client listen for data on separate thread in c++ not Delphi
我正在使用 c++ builder XE8,我只是一个初学者。我对 Delphi 一无所知。为了监听服务器端和客户端传入的数据,我从 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 event.For 我想要创建的服务器启动线程的 start() 方法它在异步模式下工作(处理至少数百个客户端)。
我能感觉到我做错了,但真的很难在 C++ 中找到一个好的例子。请有人告诉我正确的方法。
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;
}
}
我正在使用 c++ builder XE8,我只是一个初学者。我对 Delphi 一无所知。为了监听服务器端和客户端传入的数据,我从 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 event.For 我想要创建的服务器启动线程的 start() 方法它在异步模式下工作(处理至少数百个客户端)。
我能感觉到我做错了,但真的很难在 C++ 中找到一个好的例子。请有人告诉我正确的方法。
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;
}
}