SNMP getbulk 的实现

Implementation of SNMP getbulk

是否可以在 Delphi 中使用 TIdSNMP 实现 GetBulk 请求?

IdSNMP1.Query.Version:=1;    
IdSNMP1.Query.PDUType := PDUGetNextRequest;
IdSNMP1.Query.MIBAdd(OID,'',2);
while IdSNMP1.SendQuery do
begin
  if Copy (IdSNMP1.Reply.MIBOID [0], 1, Length (OID)) <> OID then break;
  Memo1.Lines.Append('Replies: ' + IdSNMP1.Reply.ValueOID [0] + '  ' + IdSNMP1.Reply.Value[0]);
  IdSNMP1.Query.MIBDelete(0);
  IdSNMP1.Query.MIBAdd(IdSNMP1.Reply.ValueOID [0], '');
  IdSNMP1.Query.PDUType := PDUGetNextRequest;
end

结果,我得到了一个get-response,我想实现完整的GetBulk

您没有考虑到响应可能包含多个 OID 值。您只查看每个回复的第一个 OID。 Reply 属性 有一个 ValueCount 属性,你应该遍历所有的值,然后使用最后提供的 OID 发送下一个请求,例如:

IdSNMP1.Query.Version := 1;    
IdSNMP1.Query.PDUType := PDUGetNextRequest;
IdSNMP1.Query.MIBAdd(OID, '', ASN1_INT);
while IdSNMP1.SendQuery do
begin
  if IdSNMP1.Reply.ValueCount = 0 then Break;
  Stop := False;
  for I := 0 to IdSNMP1.Reply.ValueCount then
  begin
    Stop := (IdSNMP1.Reply.ValueOID[I] <> OID) and (not TextStartsWith(IdSNMP1.Reply.ValueOID[I], OID+'.'));
    if Stop then Break;
    Memo1.Lines.Append('Replies: ' + IdSNMP1.Reply.ValueOID[I] + '  ' + IdSNMP1.Reply.Value[I]);
  end;
  if Stop then Break;
  IdSNMP1.Query.MIBDelete(0);
  IdSNMP1.Query.MIBAdd(IdSNMP1.Reply.ValueOID[IdSNMP1.Reply.ValueCount-1], '');
end

话虽这么说,TIdSNMP 主要仅实施 SNMP v1, however GETBULK was introduced in SNMP v2. There is a workitem 来更新 TIdSNMP 以支持更新的 SNMP 版本。同时,SNMP v2c 消息(与 v2p 或 v2u 相对)在某种程度上 与 SNMP v1 消息兼容,因此您可能能够做到类似于以下内容:

const
  PDUGetBulkRequest = $a5;

IdSNMP1.Query.Version := 1;
IdSNMP1.Query.PDUType := PDUGetBulkRequest;
IdSNMP1.Query.ID := ...; // desired request-id value
IdSNMP1.Query.ErrorStatus := ...; // desired non-repeaters value
IdSNMP1.Query.ErrorIndex := ...; // desired max-repetitions value
IdSNMP1.Query.MIBAdd(OID, '', ASN1_INT);
while IdSNMP1.SendQuery do
begin
  if IdSNMP1.Reply.ValueCount = 0 then Break;
  Stop := False;
  for I := 0 to IdSNMP1.Reply.ValueCount then
  begin
    Stop := (IdSNMP1.Reply.ValueOID[I] <> OID) and (not TextStartsWith(IdSNMP1.Reply.ValueOID[I], OID+'.'));
    if Stop then Break;
    Memo1.Lines.Append('Replies: ' + IdSNMP1.Reply.ValueOID[I] + '  ' + IdSNMP1.Reply.Value[I]);
  end;
  if Stop then Break;
  IdSNMP1.Query.MIBDelete(0);
  IdSNMP1.Query.MIBAdd(IdSNMP1.Reply.ValueOID[IdSNMP1.Reply.ValueCount-1], '');
end