Как получить ловушку с помощью компонента Indy TidSNMP

Я использую c ++ builderXE с Indy 10.5.7 и пытаюсь получить ловушку от другого агента snmp.

У меня нет информации, описывающей, как сделать программу для приема ловушки.

Ниже вы можете найти фрагмент кода, который я пытаюсь использовать сейчас.

Метод ReceiveTrap () всегда возвращает 0, что означает, что данные не получены.

Я протестировал конфигурацию ПК с другой программой, которую я сделал несколько лет назад с использованием запасного API, и получено прерывание, поэтому я не знаю, что это должна быть проблема конфигурации.

Есть ли у вас какие-нибудь предложения относительно того, что я ошибаюсь в приведенной ниже рутине?

void __fastcall TForm1::LabelReceiveTrapClick(TObject * Sender)
{
    static bool status = false;
    int ists;
    String Fun           = "[SimpleReceiveTrap] ";
    TSNMPInfo * infoSnmp = 0;

    try
    {
        status = !status;

        if (status)
        {
            std::auto_ptr< TIdSNMP >clientSnmp(new TIdSNMP(NULL));
            clientSnmp->Community      = "public";
            clientSnmp->ReceiveTimeout = 1000;
            clientSnmp->Binding->Port  = 162;
            while (status)
            {
                Application->ProcessMessages();
                ists = clientSnmp->ReceiveTrap();
                Mylog(L"%s ReceiveTrap status = [%d]", Fun.c_str(), ists);
                if (ists > 0)
                {
                    infoSnmp = clientSnmp->Trap;
                }
            }
        }
    }
    catch (Exception & ex)
    {
        Mylog(L"%s ERROR", Fun.c_str(), ex.Message.c_str());
    }
}

person enzo1959    schedule 09.08.2012    source источник


Ответы (2)


Это неправильный способ установить порт прослушивания для приема ловушек. Чтение свойства Binding выделяет и привязывает сокет к локальному IP / порту с использованием свойств TIdSNMP::BoundIP и TIdSNMP::BoundPort. Вы не можете изменить локальный Port этого сокета после того, как он уже был привязан, поэтому ваше присвоение свойства Binding->Port фактически не работает.

Если на то пошло, вы все равно пытаетесь манипулировать не тем сокетом. Сокет Binding используется для отправки запросов удаленной системе SNMP. TIdSNMP использует отдельный сокет для приема ловушек. TIdSNMP имеет отдельное свойство TrapPort для указания порта прослушивания этого сокета. При доступе к Binding сокет ловушки выделяется и привязывается к Binding->IP и TIdSNMP::TrapPort. Свойство TrapPort по умолчанию - 162.

std::auto_ptr< TIdSNMP >clientSnmp(new TIdSNMP(NULL));
clientSnmp->Community = "public";
clientSnmp->ReceiveTimeout = 1000;
clientSnmp->TrapPort = 162; // <--
...
ists = clientSnmp->ReceiveTrap();

Глядя на журнал изменений Indy, можно увидеть, что с момента выпуска 10.5.7 в прослушивающем сокете произошли некоторые изменения, связанные с ловушками, поэтому вам может потребоваться перейти на более новую версию Indy, чтобы получить исправления ошибок. Или вы можете загрузить последнюю версию, а затем просто добавить IdSNMP.pas напрямую в свой проект, по крайней мере.

person Remy Lebeau    schedule 10.08.2012

Используя только компонент Indi, я не могу прочитать trap rev 2c Но я нашел решение с использованием TWSocket и TSNMPInfo, которое, похоже, работает хорошо

Ниже код, который я использовал:

Для получения данных я использую TWSocket из набора компонентов FPiette:

void __fastcall TForm1::LabelStartServerTracSnmpClick(TObject * Sender)
{
    String Fun = "[LabelStartServerTracSnmp] ";
    try
    {
        if (WSocket1->State == wsClosed)
        {
            WSocket1->Proto = "udp";
            WSocket1->Addr  = "0.0.0.0";
            WSocket1->Port  = 162;
            WSocket1->Listen();
        }
        else
        {
            WSocket1->Close();
        }
    }
    catch (Exception & ex)
    {
        Mylog(L"%s ERROR: [%s]", Fun.c_str(), ex.Message.c_str());
    }
}

Для анализа полученных данных использую Indy

void __fastcall TForm1::WSocket1DataAvailable(TObject * Sender, WORD ErrCode)
{
    char buffer[1024];
    int len, cnt, srcLen;
    TSockAddrIn srcSocket;
    String rcvmsg, remHost, s1, s2, Fun = "[WSocket1DataAvailable] ";
    TIdSNMP * clientSnmp = NULL;
    TSNMPInfo * infoSnmp = NULL;
    try
    {
        srcLen = sizeof(srcSocket);
        len    = WSocket1->ReceiveFrom(buffer, sizeof(buffer), srcSocket, srcLen);
        if (len >= 0)
        {
            buffer[len] = 0;
            rcvmsg      = String(buffer, len);

            __try
            {
                clientSnmp = new TIdSNMP(NULL);
                infoSnmp   = new TSNMPInfo(clientSnmp);
                infoSnmp->DecodeBuf(rcvmsg);
                cnt = infoSnmp->ValueCount;
                if (cnt > 0)
                {
                    // ---------------------------------------------------
                    for (int idx = 0; idx < cnt; ++idx)
                    {
                        s1 = infoSnmp->ValueOID[idx];
                        s2 = infoSnmp->Value[idx];
                        Mylog(L"[%s] Trap : [%s] => [%s]", s1.c_str(), s2.c_str());
                    }
                }
            }
            __finally
            {
                if (infoSnmp)
                {
                    delete infoSnmp;
                    infoSnmp = 0;
                }
                if (clientSnmp)
                {
                    delete clientSnmp;
                    clientSnmp = 0;
                }
            }
        }
    }
    catch (Exception & ex)
    {
        Mylog(L"%s ERROR", Fun.c_str(), ex.Message.c_str());
    }

}
person enzo1959    schedule 03.09.2012