Channels
The library uses abstract communication channels to send and receive bytes "over the wire". The following channel types are supported:
- TCP client / server
- TLS client / server
- UDP
- Serial
The manager that you created previously is now ready to have some channels bound to it. Adding a channel to the manager
does not make it attempt to open the channel immediately. If it's a TCP socket or serial port it won't try to open until you bind at least one outstation
or master session and enable it. Here's an example of how you go about adding a TCP client. Assume we have a DNP3Manager
called 'manager':
auto channel = manager.AddTCPClient( // alias used in log messages "tcpclient", // bitfield used to filter what gets logged levels::NORMAL | levels::ALL_APP_COMMS, // determines how connections will be retried ChannelRetry::Default(), // List of endpoints or DNS host names to cycle through { IPEndpoint("127.0.0.1", 20000) }, // IP address of the local ethernet adapter (0.0.0.0 == any adapter) "0.0.0.0", // optional listener interface for monitoring the channel PrintingChannelListener::Create(), );
There is a Add<channel type>
method on DNP3Manager
for each channel type. Refer to the C++ doxygen documentation
for details.
Exponential back-off
The ChannelRetry
configuration specifies two timing parameters for the minimum and maximum connection retry times using an exponential back-off strategy. If you don't want
exponential back-off, just set the minimum and maximum to the same value for a consistent delay. Exponential back-off really only makes sense for initiating TCP connections.
For instance if you set the minimum to TimeDuration::Seconds(3)
and the maximum to TimeDuration::Seconds(40)
a series of failed connections would have the following
time gaps between attempts.
3, 6, 12, 24, 40, 40, .....
Monitoring channels
Most of the time your communication channel is open and passing dnp3 traffic back and forth. Sometimes, however, things can go wrong with your network or you have mis-configured your connection. when
creating your channel, you can pass in a shared_ptr<IChannelListener>
to monitor the state of channel. This interface provides a method returning an enumeration of the states of the channel:
enum class ChannelState : uint8_t { /// offline and idle CLOSED = 0, /// trying to open OPENING = 1, /// open OPEN = 2, /// stopped and will never do anything again SHUTDOWN = 3 };
Cleaning up
Channels and all the sessions bound to them are automatically cleaned up when the DNP3Manager goes out of scope
(or is deleted if allocated dynamically). You can manually remove a channel without having to stop every master or outstation bound
to it by calling IChannel::Shutdown()
.
// permanently shutdown the channel channel->Shutdown();
Calls to Shutdown() are idempotent. The resources for the underlying channel will be freed
when you drop the reference to the shared_ptr<IChannel>
.