【问题标题】:Indy UDP Server very low speedIndy UDP Server 速度极低
【发布时间】:2018-07-15 05:22:15
【问题描述】:

我正在使用带有 Indy 10 的 RAD Studio 10.2,这是一个组件 IdUDPServer。 为了测试UDP连接的速度,我安装了程序UDP Test Tool

我的 UDP 服务器速度检查代码:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

int readCounter = 0;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Memo1->Clear();
    TIdSocketHandle *SocketHandle = IdUDPServer1->Bindings->Add();
    SocketHandle->IP = "127.0.0.1";
    SocketHandle->Port = 14014;
    IdUDPServer1->Active = true;
    if (IdUDPServer1->Active == true) {
        Memo1->Lines->Add("Сервер стартовал");
        Button1->Enabled = false;
        Button2->Enabled = true;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    Memo1->Clear();
    IdUDPServer1->Active = false;
    IdUDPServer1->Bindings->Clear();
    if(IdUDPServer1->Active == false) {
        Memo1->Lines->Add("Сервер остановлен");
        Button1->Enabled = true;
        Button2->Enabled = false;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData,
          TIdSocketHandle *ABinding)
{
    readCounter++;
    Edit1->Text = readCounter;

    char* szBuff = new char[AData.Length];
    memset(szBuff, 0, AData.Length);
    BytesToRaw(AData, szBuff, AData.Length);
    Memo1->Lines->Add(ToHex(AData));
    Memo1->Clear();
    delete szBuff;
}
//---------------------------------------------------------------------------

我使用IdUDPServer1UDPRead 方法中的readCounter 稍后与通过下载的测试实用程序发送的数据包数进行比较,但计数器不匹配。可以看出组件IdUDPServer很晚了。

可能是什么问题?

【问题讨论】:

    标签: sockets c++builder indy


    【解决方案1】:

    TIdUDPServer::ThreadedEvent 属性默认为false。这意味着每次服务器接收到数据包时,您的OnUDPRead 事件处理程序都会通过TThread::Synchronize() 与主 UI 线程同步同步。当然,这会降低服务器的整体性能。

    为了让您的服务器更快地响应 UDP 数据包,您需要让您的OnUDPRead 事件处理程序更快地将控制权返回给TIdUDPServer。这意味着将ThreadedEvent 设置为true 以跳过TThread::Synchronize() 调用,根本不访问用户界面(或者,至少,使用TThread::Queue()TIdNotify 异步更新用户界面 ),并删除任何减慢处理程序速度的无用代码(您正在分配和填充一个根本没有用于任何事情的 char[] 缓冲区,所以这只是浪费了开销)。

    例如,如果您使用基于 Clang 的编译器:

    // make sure ThreadedEvent=true...
    void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData, TIdSocketHandle *ABinding)
    {
        ++readCounter;
        TThread::Queue(nullptr,
            [=]() {
                Edit1->Text = readCounter;
                Memo1->Lines->Add(ToHex(AData));
            }
        );
    }
    

    否则,如果您使用的是经典编译器:

    // See "Handling Anonymous Method Types in C++":
    // http://docwiki.embarcadero.com/RADStudio/en/How_to_Handle_Delphi_Anonymous_Methods_in_C%2B%2B
    
    class TMyQueueProc : public TCppInterfacedObject<TThreadProcedure>
    {
    private:
        int m_counter;
        TIdBytes m_bytes;
    
    public:
        TMyQueueProc(int ACounter, const TIdBytes &AData) : m_counter(ACounter), m_bytes(AData) {}
        INTFOBJECT_IMPL_IUNKNOWN(TInterfacedObject);
    
        void __fastcall Invoke()
        {
            Form1->Edit1->Text = m_counter;
            Form1->Memo1->Lines->Add(ToHex(m_bytes));
        }
    };
    
    // make sure ThreadedEvent=true...
    void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData, TIdSocketHandle *ABinding)
    {
        ++readCounter;
        TThread::Queue(NULL, _di_TThreadProcedure(new TMyQueueProc(readCounter, AData)));
    }
    

    或者:

    #include <IdSync.hpp>
    
    class TMyNotify : public TIdNotify
    {
    private:
        int m_counter;
        TIdBytes m_bytes;
    
    protected:
        void __fastcall DoNotify()
        {
            Form1->Edit1->Text = m_counter;
            Form1->Memo1->Lines->Add(ToHex(m_bytes));
        }
    
    public:
        TMyNotify(int ACounter, const TIdBytes &AData) : TIdNotify(), m_counter(ACounter), m_bytes(AData) {}
     };
    
    // make sure ThreadedEvent=true...
    void __fastcall TForm1::IdUDPServer1UDPRead(TIdUDPListenerThread *AThread, const TIdBytes AData, TIdSocketHandle *ABinding)
    {
        ++readCounter;
        (new TMyNotify(readCounter, AData))->Notify();
    }
    

    【讨论】:

    • 雷米,非常感谢,你真的帮了大忙。我希望您在困难时期对 Indy 图书馆有所帮助!
    猜你喜欢
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 2019-01-05
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多