Reconnecting
Setting up reconnect
Simple and elegant way to perform reconnect is setting up a timer, which checks periodically state of the connection and reacts in case the connection is lost. Timer events are safer because they are system maintained thus usually do not interfere with multithreading that is done by the library.
Complete source code
Source code used in this chapter is extracted from Windows Service Example in C# complete source code for Microsoft Visual Studio 2008+ which is included in samples contained within archive/installation package.
Please review the example for more detailed comments and details which were removed here to better focus on crucial parts of the solution.
In the example below timer is System.Timers.Timer class object with it's
AutoReset property set to false. Then in a place where the application is initialized timer
is started for it's first lap:
protected override void OnStart(string[] args)
{
// [...]
// Signal for automatic reconnecting that
// service initialization is finished
bServiceReady = true;
// Start timer for first lap
TimerReconnect.Enabled = true;
}
Actually reconnecting
Once timer fires it's Elapsed event then the following code is executed:
private void TimerReconnect_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
if (bServiceReady && !bConnected) {
// Connect to the SMSC
int result = clientSMPP.tcpConnect("localhost", 2345, "");
if (result != 0) {
// Failed to connect with the SMSC
} else {
// Initialize session
result = clientSMPP.smppInitializeSession(
"id", "password", 1, 1, "123456");
if (result != 0) {
// Failed to initialize session with SMSC
} else {
// Connected & initialized properly
bConnected = true;
}
}
}
// Retrigger the reconnect timer
TimerReconnect.Enabled = true;
}
There are two important boolean flags to consider bServiceReady and
bConnected.
First of them signals application is ready to service connections. It should be set to true after everything
that is needed is properly initialized and set to false before the application's shutdown, when the connections
should not be restored anymore. In Windows Service application such a place is typically between OnStart and OnStop methods.
Second variable bConnected monitors connection state. It is set to
true after the connection has been properly established and initialized and set to false inside
OnTcpDisconnected event:
private void clientSMPP_OnTcpDisconnected(object sender,
smscc.tcpDisconnectedEventArgs e)
{
bConnected = false;
// [...]
}
It is also important that in the approach proposed at the very end of the Elapsed event code timer has to
be retriggered for another lap. This is because timer has AutoReset property set to false and
it allows to avoid having another event triggered when reconnect procedure takes longer than timespan between events
which may happen e.g. because of lengthy DNS lookups, network issues etc.
Shutting down
Finally, when automatic reconnect has to be stopped:
protected override void OnStop()
{
// Signal for automatic reconnecting that
// service shutdown has been started
bServiceReady = false;
// Stop reconnecting
TimerReconnect.Enabled = false;
// Disconnect from the SMSC
clientSMPP.tcpDisconnect();
// [...]
}
Conclusion
What seems elegant about this approach is that there is only one place where the connection is actually created and initialized. Both connecting an reconnecting happens in the same timer event.
Inside OnTcpDisconnected event
Another, maybe even more intuitive method, formerly disallowed but from version 7 of the library perfectly legitimate is
to make reconnect inside the code of the library's
OnTcpDisconnected event. Formerly calling tcpConnect from inside the event would result in
an error. It was pointed out that it may be necessary e.g. in the case of often dropped connections to retry reconnect
in fastest way possible. It has been altered and now reconnect procedure can be initiated directly from the code of OnTcpDisconnected event.
It requires however emphasizing that this method performs only one reconnect and if the SMSC would be unreachable at this time some other method with a repetitive attempts is necessary. So in turn similar to above depicted routine is required, just started for the first time from the event's code.
Why there is no automatic reconnect built in?
There is no automatic reconnect among functionality offered by the library. Decision not to implement it was conscious and is supported by a vast set of arguments.
Reconnecting is at least two step process which consists of establishing connection on TCP/IP level first and initialization on SMSC protocol level as a second step. Implementing reconnect would join and hide these two steps inside library thus hiding results, as error codes, returned by particular operations. It would also remove certain flexibility. One can imagine different ways of reestablishing connection in custom applications e.g. reconnect synchronized with different events, different reaction on errors on various steps of reconnect process etc.