-
Notifications
You must be signed in to change notification settings - Fork 58
Example Async Receive SNMP Trap
qingxiao_ren edited this page Sep 5, 2018
·
1 revision
Example tested with SnmpSharpNet version 0.7.3.
This example shows how to use Socket class with async receive functionality in a WinForms GUI application without network
causing negative impact on GUI operation. This example will correctly parse and display information in SNMPv1-TRAP, SNMPV2-TRAP
and SNMPV2-INFORM format.
Critical methods in this example are Socket.BeginReceiveFrom(), Socket.EndReceiveFrom()
Example is a very simple application containing a check box (displayed as on/off button) that allows users to enable or disable
SNMP trap/inform reception and a list box that dumps trap, inform and error information.
using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using SnmpSharpNet;
namespace AsyncTrapReceiver
{
public class Form1 : Form
{
protected Socket _socket;
protected byte[] _inbuffer;
protected IPEndPoint _peerIP;
private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.CheckBox startCheckBox;
public Form1 ()
{
// it is not neccessary to initialize variables to null, but better safe then sorry
_socket = null;
this.listBox1 = new System.Windows.Forms.ListBox ();
this.startCheckBox = new System.Windows.Forms.CheckBox ();
this.SuspendLayout ();
//
// listBox1
//
this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)
((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point (13, 13);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size (328, 368);
this.listBox1.TabIndex = 0;
//
// startCheckBox
//
this.startCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)
((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.startCheckBox.Appearance = System.Windows.Forms.Appearance.Button;
this.startCheckBox.Location = new System.Drawing.Point (347, 12);
this.startCheckBox.Name = "startCheckBox";
this.startCheckBox.Size = new System.Drawing.Size (75, 24);
this.startCheckBox.TabIndex = 3;
this.startCheckBox.Text = "&Start";
this.startCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.startCheckBox.UseVisualStyleBackColor = true;
this.startCheckBox.CheckedChanged += new System.EventHandler (this.onStartChanged);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF (6f, 13f);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size (434, 391);
this.Controls.Add (this.startCheckBox);
this.Controls.Add (this.listBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout (false);
}
public bool InitializeReceiver ()
{
if (_socket != null) {
StopReceiver ();
}
try {
// create an IP/UDP socket
_socket = new Socket (AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
} catch (Exception ex) {
listBox1.Items.Add ("SNMP trap receiver socket initialization failed with error: " + ex.Message);
// there is no need to close the socket because it was never correctly created
_socket = null;
}
if (_socket == null)
return false;
try {
// prepare to "bind" the socket to the local port number
// binding notifies the operating system that application
// wishes to receive data sent to the specified port number
// prepare EndPoint that will bind the application to all available
//IP addresses and port 162 (snmp-trap)
EndPoint localEP = new IPEndPoint (IPAddress.Any, 162);
// bind socket
_socket.Bind (localEP);
} catch (Exception ex) {
listBox1.Items.Add ("SNMP trap receiver initialization failed with error: " + ex.Message);
_socket.Close ();
_socket = null;
}
if (_socket == null)
return false;
if (!RegisterReceiveOperation ())
return false;
return true;
}
public void StopReceiver ()
{
if (_socket != null) {
_socket.Close ();
_socket = null;
}
}
public bool RegisterReceiveOperation ()
{
if (_socket == null)
return false;
// socket has been closed
try {
_peerIP = new IPEndPoint (IPAddress.Any, 0);
// receive from anybody
EndPoint ep = (EndPoint)_peerIP;
_inbuffer = new byte[64 * 1024];
// nice and big receive buffer
_socket.BeginReceiveFrom (_inbuffer, 0, 64 * 1024,
SocketFlags.None, ref ep, new AsyncCallback (ReceiveCallback), _socket);
} catch (Exception ex) {
listBox1.Items.Add ("Registering receive operation failed with message: " + ex.Message);
_socket.Close ();
_socket = null;
}
if (_socket == null)
return false;
return true;
}
private void ReceiveCallback (IAsyncResult result)
{
// get a reference to the socket. This is handy if socket has been closed elsewhere in the class
Socket sock = (Socket)result.AsyncState;
_peerIP = new IPEndPoint (IPAddress.Any, 0);
// variable to store received data length
int inlen;
try {
EndPoint ep = (EndPoint)_peerIP;
inlen = sock.EndReceiveFrom (result, ref ep);
_peerIP = (IPEndPoint)ep;
} catch (Exception ex) {
// only post messages if class socket reference is not null
// in all other cases, user has terminated the socket
if (_socket != null) {
PostAsyncMessage ("Receive operation failed with message: " + ex.Message);
}
inlen = -1;
}
// if socket has been closed, ignore received data and return
if (_socket == null)
return;
// check that received data is long enough
if (inlen <= 0) {
// request next packet
RegisterReceiveOperation ();
return;
}
int packetVersion = SnmpPacket.GetProtocolVersion (_inbuffer, inlen);
if (packetVersion == (int)SnmpVersion.Ver1) {
SnmpV1TrapPacket pkt = new SnmpV1TrapPacket ();
try {
pkt.decode (_inbuffer, inlen);
} catch (Exception ex) {
PostAsyncMessage ("Error parsing SNMPv1 Trap: " + ex.Message);
pkt = null;
}
if (pkt != null) {
PostAsyncMessage (String.Format ("** SNMPv1 TRAP from {0}", _peerIP.ToString ()));
PostAsyncMessage (
String.Format ("*** community {0} generic id: {1} specific id: {2}",
pkt.Community, pkt.Pdu.Generic, pkt.Pdu.Specific)
);
PostAsyncMessage (String.Format ("*** PDU count: {0}", pkt.Pdu.VbCount));
foreach (Vb vb in pkt.Pdu.VbList) {
PostAsyncMessage (
String.Format ("**** Vb oid: {0} type: {1} value: {2}",
vb.Oid.ToString (), SnmpConstants.GetTypeName (vb.Value.Type), vb.Value.ToString ())
);
}
PostAsyncMessage ("** End of SNMPv1 TRAP");
}
} else if (packetVersion == (int)SnmpVersion.Ver2) {
SnmpV2Packet pkt = new SnmpV2Packet ();
try {
pkt.decode (_inbuffer, inlen);
} catch (Exception ex) {
PostAsyncMessage ("Error parsing SNMPv1 Trap: " + ex.Message);
pkt = null;
}
if (pkt != null) {
if (pkt.Pdu.Type == PduType.V2Trap) {
PostAsyncMessage (String.Format ("** SNMPv2 TRAP from {0}", _peerIP.ToString ()));
} else if (pkt.Pdu.Type == PduType.Inform) {
PostAsyncMessage (String.Format ("** SNMPv2 INFORM from {0}", _peerIP.ToString ()));
} else {
PostAsyncMessage (String.Format ("Invalid SNMPv2 packet from {0}", _peerIP.ToString ()));
pkt = null;
}
if (pkt != null) {
PostAsyncMessage (
String.Format ("*** community {0} sysUpTime: {1} trapObjectID: {2}",
pkt.Community, pkt.Pdu.TrapSysUpTime.ToString (), pkt.Pdu.TrapObjectID.ToString ())
);
PostAsyncMessage (String.Format ("*** PDU count: {0}", pkt.Pdu.VbCount));
foreach (Vb vb in pkt.Pdu.VbList)
{
PostAsyncMessage (
String.Format ("**** Vb oid: {0} type: {1} value: {2}",
vb.Oid.ToString (), SnmpConstants.GetTypeName (vb.Value.Type), vb.Value.ToString ())
);
}
if (pkt.Pdu.Type == PduType.V2Trap)
PostAsyncMessage ("** End of SNMPv2 TRAP");
else {
PostAsyncMessage ("** End of SNMPv2 INFORM");
// send ACK back to the INFORM sender
SnmpV2Packet response = pkt.BuildInformResponse ();
byte[] buf = response.encode ();
_socket.SendTo (buf, (EndPoint)_peerIP);
}
}
}
}
RegisterReceiveOperation ();
}
protected delegate void PostAsyncMessageDelegate (string msg);
protected void PostAsyncMessage (string msg)
{
if (InvokeRequired)
Invoke (new PostAsyncMessageDelegate (PostAsyncMessage), new object[] { msg });
else
listBox1.Items.Add (msg);
}
private void onStartChanged (object sender, EventArgs e)
{
if (startCheckBox.Checked) {
if (!InitializeReceiver ()) {
// unable to start TRAP receiver
startCheckBox.Checked = false;
return;
} else {
startCheckBox.Text = "S&top";
}
} else {
StopReceiver ();
startCheckBox.Text = "&Start";
}
}
}
}
Same thing in VB.Net
Imports System
Imports System.Windows.Forms
Imports System.Net
Imports System.Net.Sockets
Imports SnmpSharpNet
Public Class Form1
Inherits Form
Dim _socket As Socket
Dim _inbuffer() As Byte
Dim _peerIP As IPEndPoint
Dim listBox1 As System.Windows.Forms.ListBox
Dim WithEvents startCheckBox As System.Windows.Forms.CheckBox
Public Sub New()
System.Diagnostics.Debug.WriteLine("OnLoad event")
_socket = Nothing
listBox1 = New System.Windows.Forms.ListBox()
startCheckBox = New System.Windows.Forms.CheckBox()
SuspendLayout()
'
' listBox1
'
listBox1.Parent = Me
listBox1.Anchor = ((((System.Windows.Forms.AnchorStyles.Top Or _
System.Windows.Forms.AnchorStyles.Bottom) Or _
System.Windows.Forms.AnchorStyles.Left) Or _
System.Windows.Forms.AnchorStyles.Right))
listBox1.FormattingEnabled = True
listBox1.Location = New System.Drawing.Point(13, 13)
listBox1.Name = "listBox1"
listBox1.Size = New System.Drawing.Size(328, 368)
listBox1.TabIndex = 0
'
' startCheckBox
'
startCheckBox.Parent = Me
startCheckBox.Anchor = (System.Windows.Forms.AnchorStyles.Top Or _
System.Windows.Forms.AnchorStyles.Right)
startCheckBox.Appearance = System.Windows.Forms.Appearance.Button
startCheckBox.Location = New System.Drawing.Point(347, 12)
startCheckBox.Name = "startCheckBox"
startCheckBox.Size = New System.Drawing.Size(75, 24)
startCheckBox.TabIndex = 3
startCheckBox.Text = "&Start"
startCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
startCheckBox.UseVisualStyleBackColor = True
'
' Form1
'
AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
ClientSize = New System.Drawing.Size(434, 391)
Me.Controls.Add(startCheckBox)
Me.Controls.Add(listBox1)
Name = "Form1"
Text = "Form1"
ResumeLayout(False)
End Sub
Public Function InitializeReceiver() As Boolean
If _socket IsNot Nothing Then
StopReceiver()
End If
Try
_socket = New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
Catch ex As Exception
listBox1.Items.Add("SNMP trap receiver socket initialization failed with error: " & ex.Message)
' there is no need to close the socket because it was never correctly created
_socket = Nothing
Return False
End Try
Try
Dim ep As EndPoint = New IPEndPoint(System.Net.IPAddress.Any, 162)
_socket.Bind(ep)
Catch ex As Exception
listBox1.Items.Add("SNMP trap receiver initialization failed with error: " & ex.Message)
_socket.Close()
_socket = Nothing
Return False
End Try
If RegisterReceiveOperation() = False Then
Return False
End If
Return True
End Function
Public Sub StopReceiver()
If _socket IsNot Nothing Then
_socket.Close()
_socket = Nothing
End If
End Sub
Public Function RegisterReceiveOperation() As Boolean
If _socket Is Nothing Then
Return False
End If
Try
_peerIP = New IPEndPoint(System.Net.IPAddress.Any, 0) ' receive from anybody
_inbuffer = New [Byte](64 * 1024) {} ' nice and big receive buffer
_socket.BeginReceiveFrom(_inbuffer, 0, _inbuffer.Length, _
System.Net.Sockets.SocketFlags.None, _
_peerIP, New AsyncCallback(AddressOf ReceiveCallback), _socket)
Catch ex As Exception
listBox1.Items.Add("Registering receive operation failed with message: " & ex.Message)
_socket.Close()
_socket = Nothing
Return False
End Try
Return True
End Function
Public Sub ReceiveCallback(ByVal result As IAsyncResult)
Dim sock As Socket = result.AsyncState
Dim inlen As Integer
_peerIP = New IPEndPoint(System.Net.IPAddress.Any, 0)
Try
inlen = sock.EndReceiveFrom(result, _peerIP)
Catch ex As Exception
' only post messages if class socket reference is not null
' in all other cases, user has terminated the socket
If _socket IsNot Nothing Then
PostAsyncMessage("Receive operation failed with message: " & ex.Message)
End If
inlen = -1
End Try
' if socket has been closed, don't process received data
If _socket IsNot Nothing Then
' check that received data is long enough
If inlen > 0 Then
Dim packetVersion As Integer = SnmpPacket.GetProtocolVersion(_inbuffer, inlen)
If packetVersion = SnmpVersion.Ver1 Then
Dim pkt As SnmpV1TrapPacket = New SnmpV1TrapPacket
Try
pkt.decode(_inbuffer, inlen)
Catch ex As Exception
PostAsyncMessage("Error parsing SNMPv1 Trap: " + ex.Message)
pkt = Nothing
End Try
If pkt IsNot Nothing Then
PostAsyncMessage(String.Format("** SNMPv1 TRAP from {0}", _peerIP.ToString()))
PostAsyncMessage(String.Format("*** community {0} generic id: {1} specific id: {2}", _
pkt.Community, pkt.Pdu.Generic, pkt.Pdu.Specific))
PostAsyncMessage(String.Format("*** PDU count: {0}", pkt.Pdu.VbCount))
Dim vb As Vb
For Each vb In pkt.Pdu.VbList
PostAsyncMessage(String.Format("**** Vb oid: {0} type: {1} value: {2}", _
vb.Oid.ToString(), SnmpConstants.GetTypeName(vb.Value.Type), _
vb.Value.ToString()))
Next
PostAsyncMessage("** End of SNMPv1 TRAP")
End If
ElseIf packetVersion = SnmpVersion.Ver2 Then
Dim pkt As SnmpV2Packet = New SnmpV2Packet
Try
pkt.decode(_inbuffer, inlen)
Catch ex As Exception
pkt = Nothing
End Try
If pkt.Pdu.Type = PduType.V2Trap Then
PostAsyncMessage(String.Format("** SNMPv2 TRAP from {0}", _peerIP.ToString()))
ElseIf pkt.Pdu.Type = PduType.Inform Then
PostAsyncMessage(String.Format("** SNMPv2 INFORM from {0}", _peerIP.ToString()))
Else
PostAsyncMessage(String.Format("Invalid SNMPv2 packet from {0}", _peerIP.ToString()))
pkt = Nothing
End If
If pkt IsNot Nothing Then
PostAsyncMessage(String.Format("*** community {0} sysUpTime: {1} trapObjectID: {2}", _
pkt.Community, pkt.Pdu.TrapSysUpTime.ToString(), pkt.Pdu.TrapObjectID.ToString()))
PostAsyncMessage(String.Format("*** PDU count: {0}", pkt.Pdu.VbCount))
Dim vb As Vb
For Each vb In pkt.Pdu.VbList
PostAsyncMessage(String.Format("**** Vb oid: {0} type: {1} value: {2}", _
vb.Oid.ToString(), SnmpConstants.GetTypeName(vb.Value.Type), vb.Value.ToString()))
Next
If pkt.Pdu.Type = PduType.V2Trap Then
PostAsyncMessage("** End of SNMPv2 TRAP")
Else
PostAsyncMessage("** End of SNMPv2 INFORM")
' send ACK back to the INFORM sender
Dim response As SnmpV2Packet = pkt.BuildInformResponse()
Dim buf() As Byte = response.encode()
_socket.SendTo(buf, _peerIP)
End If
End If
End If
RegisterReceiveOperation()
End If
End If
End Sub
Protected Delegate Sub PostAsyncMessageDelegate(ByVal msg As String)
Protected Sub PostAsyncMessage(ByVal msg As String)
If InvokeRequired Then
Dim param() As Object
param = New Object() {msg}
Invoke(New PostAsyncMessageDelegate(AddressOf PostAsyncMessage), param)
Else
listBox1.Items.Add(msg)
End If
End Sub
Private Sub OnStartChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles startCheckBox.CheckedChanged
If startCheckBox.Checked Then
If Not InitializeReceiver() Then
startCheckBox.Checked = False
Else
startCheckBox.Text = "S&top"
End If
Else
StopReceiver()
startCheckBox.Text = "&Start"
End If
End Sub
End Class