如何使用TIdSNMP从多个源接收陷阱通知

时间:2014-06-05 13:29:09

标签: delphi snmp indy

我们正在开发Delphi XE5程序,以监控本地网络中的MFP。重要的是,对于每个传入的SNMP陷阱通知,我们都能够确定发送它的MFP。似乎TIdSNMP.ReceiveTrap将自上次调用以来收到的每个通知放入TIdSNMP.Trap.Value数组属性的元素中;然后,TIdSNMP.Trap.Host包含发送最新陷阱通知的MFP的IP地址。有人可以证实这一点吗?有没有办法获得与TIdSNMP.Trap.Value的其他元素相对应的IP地址?

出于测试目的,我们使用以下代码来接收和显示SNMP陷阱消息:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient, IdSNMP;

type
  TForm1 = class(TForm)
    Button2: TButton;
    IdSNMP1: TIdSNMP;
    Memo1: TMemo;
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);

  procedure FormatTrap(ASnmpInfo : TSnmpInfo);
  var
    i : integer;
  begin
    Memo1.Lines.Add('{');
    with ASnmpInfo do begin
      Memo1.Lines.Add(Format('Host=%s, ', [Host]));
      Memo1.Lines.Add(Format('Port=%d, ', [Port]));
      Memo1.Lines.Add(Format('Enterprise=%s, ', [Enterprise]));
      Memo1.Lines.Add(Format('GenTrap=%d, ', [GenTrap]));
      Memo1.Lines.Add(Format('SpecTrap=%d, ', [SpecTrap]));
      Memo1.Lines.Add(Format('Version=%d, ', [Version]));
      Memo1.Lines.Add(Format('PDUType=%d, ', [PDUType]));
      Memo1.Lines.Add(Format('TimeTicks=%d, ', [TimeTicks]));
      Memo1.Lines.Add(Format('ID=%d, ', [ID]));
      Memo1.Lines.Add(Format('ErrorStatus=%d, ', [ErrorStatus]));
      Memo1.Lines.Add(Format('ErrorIndex=%d, ', [ErrorIndex]));
      Memo1.Lines.Add(Format('Community=%s, ', [Community]));
      Memo1.Lines.Add(Format('ValueCount=%d, ', [ValueCount]));
      for i := 0 to ValueCount-1 do begin
        Memo1.Lines.Add( Format('Value[%d]=%s, ', [i,Value[i]]));
        Memo1.Lines.Add( Format('ValueOID[%d]=%s, ', [i,ValueOID[i]]));
        Memo1.Lines.Add( Format('ValueType[%d]=%d, ', [i,ValueType[i]]));
      end;
      Memo1.Lines.Add('}');
    end;
  end;

begin
  while not Application.Terminated do begin
    if IdSNMP1.ReceiveTrap() then begin
      FormatTrap(IdSNMP1.Trap);
    end;
    Sleep(100);
    Application.ProcessMessages();
  end;
end;

end.

两台MFP - 一台192.168.197.159下的柯尼卡美能达bizhub C364e和192.168.197.19下的柯尼卡美能达bizhub C364--已配置为向运行此程序的计算机发送SNMP陷阱通知。以下是一些示例结果:

{
Host=192.168.197.159, 
Port=32884, 
Enterprise=1.3.6.1.4.1.18334, 
GenTrap=6, 
SpecTrap=10, 
Version=0, 
 PDUType=164, 
TimeTicks=7792839, 
ID=0, 
ErrorStatus=0, 
ErrorIndex=0, 
Community=public, 
ValueCount=5, 
Value[0]=No Paper, 
ValueOID[0]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[0]=4, 
 Value[1]=No Paper, 
ValueOID[1]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[1]=4, 
Value[2]=No Paper, 
ValueOID[2]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[2]=4, 
Value[3]=No Paper, 
ValueOID[3]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
 ValueType[3]=4, 
Value[4]=Job End, 
ValueOID[4]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[4]=4, 
}

{
Host=192.168.197.19, 
Port=53365, 
Enterprise=1.3.6.1.4.1.18334, 
GenTrap=6, 
SpecTrap=10, 
Version=0, 
 PDUType=164, 
TimeTicks=12469234, 
ID=0, 
ErrorStatus=0, 
ErrorIndex=0, 
Community=public, 
ValueCount=6, 
Value[0]=No Paper, 
ValueOID[0]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[0]=4, 
 Value[1]=No Paper, 
ValueOID[1]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[1]=4, 
Value[2]=No Paper, 
ValueOID[2]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[2]=4, 
Value[3]=No Paper, 
ValueOID[3]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
 ValueType[3]=4, 
Value[4]=Job End, 
ValueOID[4]=1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2, 
ValueType[4]=4, 
Value[5]=Job End, 
ValueOID[5]=1.3.6.1.4.1.18334.1.1.1.2.1.83.3.1, 
ValueType[5]=4, 
}

1.3.6.1.4.1.18334.1.1.1.2.1.105.2.2是C364e的SysObjectID和1.3.6.1.4.1.18334.1.1.1.2.1.83.3.1 C364的SysObjectID。所以除了最后一个通知之外的所有通知都来自192.168.197.159下的MFP,尽管最后6个通知TIdSNMP.Trap.Host包含值192.168.197.19。

1 个答案:

答案 0 :(得分:2)

您描述的内容看起来像TIdSNMP.ReceiveTrap()中的错误。它不是每次都调用TIdSNMP.Trap.Clear()。它不应该随着时间的推移保留收到的陷阱的历史。我刚刚检查了Indy的SVN。如果您不想或不能升级您的Indy安装,一个简单的解决方法是在致电IdSNMP1.Trap.Clear()之前致电IdSNMP1.ReceiveTrap()

while not Application.Terminated do begin
  IdSNMP1.Trap.Clear(); // <-- add this
  if IdSNMP1.ReceiveTrap() then begin
    FormatTrap(IdSNMP1.Trap);
  end;
  Sleep(100);
  Application.ProcessMessages();
end;

话虽如此,在UI点击处理程序中使用忙循环不是一个好主意。我建议您使用TTimer代替:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  Vcl.ExtCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient, IdSNMP;

type
  TForm1 = class(TForm)
    Button2: TButton;
    IdSNMP1: TIdSNMP;
    Memo1: TMemo;
    Timer1: TTimer;
    procedure Button2Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
  Timer1.Interval := 100;
  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);

  procedure FormatTrap(ASnmpInfo : TSnmpInfo);
  var
    i : integer;
  begin
    Memo1.Lines.BeginUpdate;
    try
      Memo1.Lines.Add('{');
      Memo1.Lines.Add(Format('Host=%s, ', [ASnmpInfo.Host]));
      Memo1.Lines.Add(Format('Port=%d, ', [ASnmpInfo.Port]));
      Memo1.Lines.Add(Format('Enterprise=%s, ', [ASnmpInfo.Enterprise]));
      Memo1.Lines.Add(Format('GenTrap=%d, ', [ASnmpInfo.GenTrap]));
      Memo1.Lines.Add(Format('SpecTrap=%d, ', [ASnmpInfo.SpecTrap]));
      Memo1.Lines.Add(Format('Version=%d, ', [ASnmpInfo.Version]));
      Memo1.Lines.Add(Format('PDUType=%d, ', [ASnmpInfo.PDUType]));
      Memo1.Lines.Add(Format('TimeTicks=%d, ', [ASnmpInfo.TimeTicks]));
      Memo1.Lines.Add(Format('ID=%d, ', [ASnmpInfo.ID]));
      Memo1.Lines.Add(Format('ErrorStatus=%d, ', [ASnmpInfo.ErrorStatus]));
      Memo1.Lines.Add(Format('ErrorIndex=%d, ', [ASnmpInfo.ErrorIndex]));
      Memo1.Lines.Add(Format('Community=%s, ', [ASnmpInfo.Community]));
      Memo1.Lines.Add(Format('ValueCount=%d, ', [ASnmpInfo.ValueCount]));
      for i := 0 to ASnmpInfo.ValueCount-1 do begin
        Memo1.Lines.Add( Format('Value[%d]=%s, ', [i,ASnmpInfo.Value[i]]));
        Memo1.Lines.Add( Format('ValueOID[%d]=%s, ', [i,ASnmpInfo.ValueOID[i]]));
        Memo1.Lines.Add( Format('ValueType[%d]=%d, ', [i,ASnmpInfo.ValueType[i]]));
      end;
      Memo1.Lines.Add('}');
    finally
      Memo1.Lines.EndUpdate;
    end;
  end;

begin
  IdSNMP1.Trap.Clear();
  if IdSNMP1.ReceiveTrap() then begin
    FormatTrap(IdSNMP1.Trap);
  end;
end;

end.