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.