Version: 4.9.4.0
Create custom SNMP Manager, Trap and Agent applications for monitoring and controlling network devices. 

Designed for Modern Applications

PowerSNMP for .NET exposes a modern multi-threaded design with technical advantages over competing products.

Async Methods

The async methods (BeginXXX) seen in competing products reflect an antiquated single-threaded design model that denies the benefits of multi-threaded power. Please read on to see how PowerSNMP delivers multi-threaded power to your application without adding the complexity that is often associated with multi-threading techniques.

PowerSNMP for .NET uses 3 multi-threaded design techniques to provide an elegant and robust programming model:

  • Delegates are used for event-driven operations. Agents must respond to GetRequests and Managers must capture Traps/Informs. A simple Start(delegate) method specifies a delegate (callback method) where your code responds to received packets. No "housekeeping" code is necessary ... the request packet is already decoded and your code simply implements the desired action. Asynchronous I/O is used so thread usage is minimal.
  • Delegates are also used for client operations on a worker thread. Agents send Informs and Managers send GetRequests/Informs and receive the reply. Again, a simple Start(delegate) method is used to execute your delegate on a worker thread. Within that delegate your code sends requests and waits for replies. For enterprise applications you can spread your work over multiple threads by using Start(delegate) to execute multiple delegates in parallel.
  • As an alternative to the previous technique for sending and receiving messages, version 4.7 introduces the awaitable GetResponseTaskAsync() method. This task will execute asynchronously so no thread resource is required, making this a scalable technique. It is also awaitable, making it a useful tool for single-threaded applications with a UI.

This design eliminates the need for BeginXXX methods and EndXXX events. There is a clean interface with one method for each function and several advantages are immediately realized:

Efficiency. Methods are designed to efficiently block on socket receive operations (the thread sleeps until bytes are received). This results in the most robust and efficient design possible.

Reusable code. Your delegate(s) can be used in applications both with and without a UI. It is no longer necessary to use BeginFoo for Windows Forms applications, and (the blocking) Foo for services, web applications and console applications.

Lower life-cycle cost. Code is written sequentially because there is no UI message pump to consider. It is not necessary to write code for numerous event handlers. Your code is self-documenting, easier to debug and maintain, and has a lower life-cycle cost.

Easy-to-implement parallel operation. Worker threads are easily spawned, supporting intensively parallel operations. Alternatively, serial operation is easily implemented by using just one thread. Flexibility of design is key.

No more state machine. It is not necessary to track state in event handlers. Take the simple case where the following sequence takes place:

  • Receive data R1
  • Send data S1
  • Receive data R2
  • Send data S2

Using BeginXXX, an event is raised when data is received and a state machine is required (if R1 is received then send S1, else if R2 is received then send S2). Using a single worker thread, the operation is coded in simple, declarative steps (Receive R1, Send S1, Receive R2, Send S2).

No More Pseudo-Blocking

Competing products use "pseudo-blocking" to process UI events while the method blocks. Without pseudo-blocking overhead methods are faster and more efficient. Also, re-entrancy problems (caused when UI messages are processes while a communication method is in progress) are no longer possible.

Developing Applications Without a UI

Developing console applications, web applications, services and other applications without a UI is as easy as ever. Sequential code performs efficiently. If parallel operation is desired, Start(delegate) can be used to execute code in any delegate body in parallel.

Developing Applications With a UI

Developing Windows Forms applications is now just as easy as writing applications without a UI. One method (the delegate) can be used in both types of applications. The only difference is that a UI app uses Start(delegate) to spawn a worker thread upon which the method executes, and any data needed by the UI must be marshaled to the UI thread. To this end, PowerSNMP components include Start() and Marshal() convenience methods.

The Start Method

Use the Start method to execute one or more functions on a new worker thread so the UI is not blocked during operation. The syntax for this method is simple:

manager1.Start(myBlockingFunction, myObject);

private void myBlockingFunction(ManagerSlave slave, object myObject)
{
    //...
}


Marshaling Data

It is often necessary to pass information from a worker thread to update an element on the UI thread. Use the Marshal method for this purpose. Each Marshal overload is paired with an event that is raised on the UI thread.

manager1.Marshal(responses, ""null); //Execute on worker thread 

private void
manager1_Message(object sender, MessageEventArgs e)
{
    //Display received messages in a UI element (raised on the UI thread)
    foreach (MessageBase message in e.Messages) { /*..*/ }
}


Typical Use

Below are two typical use examples.

In the first example, the developer wants to send a Get request and receive a response without interfering with the user-interface. A button, textbox and Manager component are added to the form. Pressing the button will send the request and wait for the response. When the response is received, the value of the requested variable is shown in the textbox. The performRequest function, which could be reused in a non-UI application, is passed to Start and executes on a worker thread (C# and VB code snippets follow).

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        //Get agent's sysDescription value
        manager1.Start(performRequest, manager1.Mib.CreateVariable(NodeName.sysDescr));
    }
    catch (Exception ex)
    {
        //Problems creating the socket will be caught here
        MessageBox.Show(ex.Message);
    }
}

private void performRequest(ManagerSlave slave, object variable)
{
    GetMessage request = null;
    try
    {
        //Create Get request and get response
        request = new GetMessage();
        request.Version = SnmpVersion.One;
        request.Variables.Add((Variable)variable);
        ResponseMessage response = slave.GetResponse(request, myAgentAddress);

        //Marshal response to UI thread
        manager1.Marshal(new ResponseMessage[] { response }, null);
    }
    catch (Exception ex)
    {
        //Marshal exception to UI thread
        manager1.Marshal(ex);
    }
}

void manager1_Message(object sender, MessageEventArgs e)
{
    //Show value of first variable
    ResponseMessage response = e.Messages[0] as ResponseMessage;
    textBox1.Text = response.Variables[0].Value.ToString();
}

private void manager1_Error(object sender, ErrorEventArgs e)
{
    //Show exception
    MessageBox.Show(e.GetException().Message);
}


In the second example, the developer starts a thread for receiving request messages from SNMP managers. Similar code is used for the manager component to listen for trap, notification and inform messages.

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        //Start a thread for receiving requests
        agent1.Start(requestReceived, null);
    }
    catch (Exception ex)
    {
        //Problems with the socket will be caught here
        MessageBox.Show(ex.Message);
    }
}

void requestReceived(Agent agent, RequestMessage request, object state)
{
    //Create and send a response for the request
    ResponseMessage response = agent1.CreateDefaultResponse(request);
    agent1.Send(response, request.Origin);

    //Also, log any set requests received
    if (request is SetMessage)
        agent1.Marshal(new ResponseMessage[] { response }, "", null);
}

void agent1_Message(object sender, MessageEventArgs e)
{
    //Log returned variables
    ResponseMessage response = e.Messages[0] as ResponseMessage;
    foreach (Variable v in response.Variables)
        logSetRequest(v.Id, v.Value); //function not included in example code
}