Как получить ловушку с инди-компонентом 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());
    }
}

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 к вашему проекту напрямую, по крайней мере.

Используя только компонент 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());
    }
}

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

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

}
Другие вопросы по тегам