问题
I made the following routine in c++builder Xe ( listing code 1 ), using the Indi component TIdSNMP to query an agent snmp.
The call to SendQuery failed, the connection is ok but the agent always return nothing.
I also try to query the agent using the method QuickSend ( listing code 2 ) and in this case this second routine work correclty, so I suppose I made some mistake using the first routine.
Can someone tell me where I was wrong in the first routine ?
Best Reagrds, Enzo
Listing 1
void __fastcall TForm1::LabelSimpleSnmpCallClick(TObject * Sender)
{
String s1, s2, hostTarget = Edit_SnmpServer->Text, sysDescr = "1.3.6.1.2.1.1.1.0", sysUpTime = "1.3.6.1.2.1.1.3.0";
TIdSNMP * clientSnmp = 0;
TSNMPInfo * infoSnmp = 0;
std::auto_ptr< TStringList >sl1(new TStringList());
std::auto_ptr< TStringList >sl2(new TStringList());
Mylog(Format("Test simple SNMP call on server [%s]", ARRAYOFCONST((hostTarget))));
try
{
__try
{
clientSnmp = new TIdSNMP(NULL);
clientSnmp->Host = hostTarget;
clientSnmp->Community = "pubblic";
clientSnmp->ReceiveTimeout = 6000;
clientSnmp->Connect();
if (clientSnmp->Connected())
{
clientSnmp->Query->Clear();
clientSnmp->Query->MIBAdd(sysDescr, "");
clientSnmp->Query->MIBAdd(sysUpTime, "");
clientSnmp->Query->PDUType = PDUGetRequest;
clientSnmp->SendQuery();
infoSnmp = clientSnmp->Reply;
if (infoSnmp->ValueCount > 0)
{
sl1->Clear();
sl2->Clear();
sl1->AddStrings(infoSnmp->MIBOID);
sl2->AddStrings(infoSnmp->MIBValue);
for (int idx = 0; idx < sl1->Count; idx++)
{
s1 = sl1->Strings[idx];
s2 = sl2->Strings[idx];
Mylog(Format("Query on [%s] : [%s] => [%s]", ARRAYOFCONST((hostTarget, s1, s2))));
}
}
else
{
Mylog("*** No anwser *** ");
}
}
else
{
Mylog("*** No connected *** ");
}
}
__finally
{
if (clientSnmp)
{
delete clientSnmp;
clientSnmp = 0;
}
}
}
catch (Exception & ex)
{
Mylog(Format("ERROR [%s] ", ARRAYOFCONST((ex.Message))));
}
}
Listing 2
void __fastcall TForm1::LabelQuickSendClick(TObject * Sender)
{
TIdSNMP * clientSnmp = 0;
String hostTarget = Edit_SnmpServer->Text, sysDescr = "1.3.6.1.2.1.1.1.0", sysUpTime = "1.3.6.1.2.1.1.3.0", val;
__try
{
clientSnmp = new TIdSNMP(NULL);
clientSnmp->ReceiveTimeout = 6000;
clientSnmp->QuickSend(sysDescr, "public", hostTarget, val);
Mylog(Format("Query on [%s] : [%s] => [%s]", ARRAYOFCONST((hostTarget, sysDescr, val))));
clientSnmp->QuickSend(sysUpTime, "public", hostTarget, val);
Mylog(Format("Query on [%s] : [%s] => [%s]", ARRAYOFCONST((hostTarget, sysUpTime, val))));
}
__finally
{
delete clientSnmp;
}
}
回答1:
In listing 1, you are setting the Community
to "pubblic"
, but in listing 2 you are setting it to "public"
instead. That makes a big difference in SNMP.
As for the rest of the code, I would suggest the following changes to simplify the code:
void __fastcall TForm1::LabelSimpleSnmpCallClick(TObject * Sender)
{
String hostTarget = Edit_SnmpServer->Text;
String sysDescr = "1.3.6.1.2.1.1.1.0";
String sysUpTime = "1.3.6.1.2.1.1.3.0";
Mylog(Format("Test simple SNMP call on server [%s]", ARRAYOFCONST((hostTarget))));
try
{
std::auto_ptr<TIdSNMP> clientSnmp(TIdSNMP(NULL));
clientSnmp->Host = hostTarget;
clientSnmp->Community = "public";
clientSnmp->ReceiveTimeout = 6000;
clientSnmp->Query->PDUType = PDUGetRequest;
clientSnmp->Query->MIBAdd(sysDescr, "");
clientSnmp->Query->MIBAdd(sysUpTime, "");
if (clientSnmp->SendQuery())
{
int cnt = clientSnmp->Reply->ValueCount;
if (cnt > 0)
{
for (int idx = 0; idx < cnt; ++idx)
{
String s1 = clientSnmp->Reply->ValueOID[idx];
String s2 = clientSnmp->Reply->Value[idx];
Mylog(Format("Query on [%s] : [%s] => [%s]", ARRAYOFCONST((hostTarget, s1, s2))));
}
}
else
{
Mylog("*** No anwser *** ");
}
}
else
{
Mylog("*** Query not sent *** ");
}
}
catch (const Exception & ex)
{
Mylog(Format("ERROR [%s] ", ARRAYOFCONST((ex.Message))));
}
}
If you overload Mylog()
to accept a variable number of parameters, you can simplify your logging a little bit:
void __fastcall TForm1::Mylog(const String &Msg)
{
// use Msg as needed ...
}
void __fastcall TForm1::Mylog(const String &Msg, const TVarRec *Args, int Args_High)
{
Mylog(Format(Msg, Args, Args_High));
}
void __fastcall TForm1::LabelSimpleSnmpCallClick(TObject * Sender)
{
String hostTarget = Edit_SnmpServer->Text;
String sysDescr = "1.3.6.1.2.1.1.1.0";
String sysUpTime = "1.3.6.1.2.1.1.3.0";
Mylog("Test simple SNMP call on server [%s]", ARRAYOFCONST((hostTarget)));
try
{
std::auto_ptr<TIdSNMP> clientSnmp(TIdSNMP(NULL));
clientSnmp->Host = hostTarget;
clientSnmp->Community = "public";
clientSnmp->ReceiveTimeout = 6000;
clientSnmp->Query->PDUType = PDUGetRequest;
clientSnmp->Query->MIBAdd(sysDescr, "");
clientSnmp->Query->MIBAdd(sysUpTime, "");
if (clientSnmp->SendQuery())
{
int cnt = clientSnmp->Reply->ValueCount;
if (cnt > 0)
{
for (int idx = 0; idx < cnt; ++idx)
{
String s1 = clientSnmp->Reply->ValueOID[idx];
String s2 = clientSnmp->Reply->Value[idx];
Mylog("Query on [%s] : [%s] => [%s]", ARRAYOFCONST((hostTarget, s1, s2)));
}
}
else
{
Mylog("*** No anwser *** ");
}
}
else
{
Mylog("*** Query not sent *** ");
}
}
catch (const Exception & ex)
{
Mylog("ERROR [%s] ", ARRAYOFCONST((ex.Message)));
}
}
If you switch to String::vprintf()
instead of Format()
then you can simplify the logging a bit further:
void __cdecl TForm1::Mylog(const PChar MsgFmt, ...)
{
String Msg;
va_list args;
va_start(args, MsgFmt);
Msg.vprintf(MsgFmt, args);
va_end(args);
// use Msg as needed...
}
void __fastcall TForm1::LabelSimpleSnmpCallClick(TObject * Sender)
{
String hostTarget = Edit_SnmpServer->Text;
String sysDescr = "1.3.6.1.2.1.1.1.0";
String sysUpTime = "1.3.6.1.2.1.1.3.0";
Mylog("Test simple SNMP call on server [%s]", hostTarget.c_str());
try
{
std::auto_ptr<TIdSNMP> clientSnmp(TIdSNMP(NULL));
clientSnmp->Host = hostTarget;
clientSnmp->Community = "public";
clientSnmp->ReceiveTimeout = 6000;
clientSnmp->Query->PDUType = PDUGetRequest;
clientSnmp->Query->MIBAdd(sysDescr, "");
clientSnmp->Query->MIBAdd(sysUpTime, "");
if (clientSnmp->SendQuery())
{
int cnt = clientSnmp->Reply->ValueCount;
if (cnt > 0)
{
for (int idx = 0; idx < cnt; ++idx)
{
String s1 = clientSnmp->Reply->ValueOID[idx];
String s2 = clientSnmp->Reply->Value[idx];
Mylog("Query on [%s] : [%s] => [%s]", hostTarget.c_str(), s1.c_str(), s2.c_str());
}
}
else
{
Mylog("*** No anwser *** ");
}
}
else
{
Mylog("*** Query not sent *** ");
}
}
catch (const Exception & ex)
{
Mylog("ERROR [%s] ", ex.Message.c_str());
}
}
来源:https://stackoverflow.com/questions/11867499/indi-tidsnmp-how-use-sendquery