how to check if there is a connectivity to interne

Topics: CAB & Smart Client Software Factory
Apr 1, 2006 at 1:07 PM
originally posted by: ksunair

The whole idea of SC is to work online and offline. I couldn't find anywhere how you check you are connected or not connected. I might have missed it, could some one please let me know

Also is there a way, we can write an event broker which will trigger an event when it is connected and when it is not connected?? Code sample will be great.
Apr 3, 2006 at 11:19 AM
originally posted by: justaddwater

I'm not sure of a real slick way to detect connections... You can either just ping a site, or use somthing like this to get a true/false back for connection state.

...
using System.Runtime;
using System.Runtime.InteropServices;

...
class Program
{

DllImport("wininet.dll")
private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);

static void Main(string[] args)
{
int outData;
Console.WriteLine(InternetGetConnectedState(out outData, 0).ToString());
Console.Read();
}

I think you would just want to test on a timer of some sort and when you get the value you want, fire your event through the broker then...
Apr 4, 2006 at 5:41 AM
originally posted by: ksunair

Thanks, it helps. But curios as so many people are working on the SC-BAT, how come there is no documented approach to this issue since this is the core of smart client?
Apr 4, 2006 at 6:47 AM
originally posted by: ksunair

One more question; I would like to know what is the right place to have this one in BAT tree structure?

Currently, I created a class like the following under common folder under root structure.

using System.Runtime;
using System.Runtime.InteropServices;


namespace rootNS.Common
{
public static class Connected
{
DllImport("wininet.dll")
private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);

public static int IsConnected2Net()
{
int connected;
InternetGetConnectedState(out connected, 0);
return connected;
}
}
}


in the module, I am using it like the following

using rootNS.Common;
...
if (Connected.IsConnected2Net() == 0)
...

Is this a correct approach or is there a better way to do this?
Apr 4, 2006 at 8:37 AM
originally posted by: justaddwater

I have a seperate module "UpdateSync" that handles all this stuff, I use the Click Once API (System.Deployment) to do updates in the background and have helper classes for other network related items.
Apr 4, 2006 at 12:40 PM
originally posted by: austinlamb

If you don't want to resort to P/Invoke, I think the System.Net.NetworkInformation namespace may be another good way to go.

First, use NetworkInformation.GetAllNetworkInterfaces ( http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.networkinterface.getallnetworkinterfaces(VS.80).aspx )

Then, from the resulting array, check to see if the network is up. The event NetworkAvailabilityChanged ( http://msdn2.microsoft.com/en-us/library/system.net.networkinformation.networkchange.networkavailabilitychanged(VS.80).aspx ) gives criteria for an available network. Namely:
1. At least one of the NetworkInterfaces has an OperationalStatus of Up
2. That interface is not a tunnel or a loopback (it's NetworkInterfaceType is not Loopback or Tunnel)


Then, once connectivity is determined, just listen for the NetworkAvailabilityChanged event, and use that to move from online to offline mode and back, automatically initiating send/recieve when online, and all that wonderful connectivity-enabled goodness.

That's just my guess, though, based on the docs, I've not implemented this approach.
Apr 5, 2006 at 1:35 PM
originally posted by: austinlamb

Actually, I've just found an even easier way.

NetworkInterface.GetIsNetworkAvailable() - returns a boolean indicating if the network is available.

Just use this for initial detection, then listen for the NetworkAvailabilityChanged event to respond to changes. Awesome.
May 2, 2006 at 11:34 AM
originally posted by: ksunair

Austin,

You are correct, this is what I did, I created a event broker in the mainshell and all the child are subscribed to it so whenever there is a network change happen, the shell fires an event and all the workitems gets it and change the workstatus to offline.

This is cool.
May 3, 2006 at 8:05 AM
originally posted by: sklett

Now I'm doubting my approach :0(

I have two data access classes, online and offline. When I try to do something like save a record to the DB (online) I do it in a try statement, if I catch an exception, I set the the offline flag and store it locally. I also start a "poller" thread to check for network availability by testing the online DB connection, when it passes, it fires an event. My services subscribe to the event and round up all the local files and save them to the DB.

This method handles both network outtage and server outtage or even DB server software outtage.

However, I have never done anything like this before and I'm sure there are flaws and reasons why it's a bad idea. I would love it if you guys could point out the problems with such an approach?
May 3, 2006 at 8:21 AM
originally posted by: austinlamb

I personally find polling to be a last resort, but if you really want to know the database is up, not the network, then I guess you're stuck polling once you find you're 'offline' (meaning database is unreachable, not actually offline from the network, by your application's definition).

Keep in mind that with your current method, if you have, say, 100 clients using this app, and the database goes down (reboot or something, let's say), then they'll all get their offline flag set. Once the db comes back up they'll all be polling it trying to connect, which may flood the connection pool rather quickly on the newly-online database server. This may not be desirable - so your poll time probably shouldn't be a constant (maybe a constant + random value?) - otherwise they could all end up hitting it over and over at specified intervals, interfering with each other.

Also, you shouldn't consider yourself offline from any exception in that try block - what if, say, your stored procedure threw an error or something? So I hope you're doing more careful error checking than just try { ...db stuff... } catch (Exception e) { ...set offline... }

And lastly, when you say "all the local files" - you're storing many files to keep the local copies? Why not use a SQL Express database, or an Access database, or something like that, which could mirror the structure of your real database, to make synchronization easier (presumably)?
May 4, 2006 at 10:50 AM
originally posted by: sklett

"Keep in mind that with your current method, if you have, say, 100 clients using this app, and the database goes down (reboot or something, let's say), then they'll all get their offline flag set. Once the db comes back up they'll all be polling it trying to connect, which may flood the connection pool rather quickly on the newly-online database server. This may not be desirable - so your poll time probably shouldn't be a constant (maybe a constant + random value?) - otherwise they could all end up hitting it over and over at specified intervals, interfering with each other."

This is a very good point that I had not thought of. Luckily, I have two things going for me;
1) I will only have 5-10 users (I know you should always plan on more, but...)
2) Offline detection will happen randomly on each client, it would take an action by a user to trigger a DB hit, then in the event the DB is down, that client will start polling from that time. So if all clients are polling at the same interval but with different offsets the problem shouldn't really be an issue.

However introducing a random into the time interval would be a good workaround if they were hitting at the same time.

"Also, you shouldn't consider yourself offline from any exception in that try block - what if, say, your stored procedure threw an error or something? So I hope you're doing more careful error checking than just try { ...db stuff... } catch (Exception e) { ...set offline... }"

I'm not happy about it either, but at this time (early stages) this is exactly what I'm doing. If the ADO.net stuff had a "ConnectionFailureException" then I would be set, but they don't. I could resort to Exception message parsing, but that's ugly too. I don't have a suggestion for a clean way, I wish I did. I have found that the DB we use (our webhost's MySql server) goes down more often then our internet connection, and that's why I decided I need to handle those outages whenever they happen.

It actually really surprises me there ISN'T some sort of a connection failure exception, this would be such a useful thing to be able to respond to.

"And lastly, when you say "all the local files" - you're storing many files to keep the local copies? Why not use a SQL Express database, or an Access database, or something like that, which could mirror the structure of your real database, to make synchronization easier (presumably)?"

Also a good question. It came down to complexity, deployment and performance. The data that I'm saving locally is a business entity representing a test result. I have made the class serializable and in the event of DB outage, I just serialize each business object to a binary file (Couldn't do XML because of some odd circular reference exception I was getting, maybe later I can look at that again) Then when the DB is available I simple deserialize and pass each one to the online data access class in a separate thread. The user never knows it happened (unless several days have passed, then I alert them in case it's a bad cable, lose cable, etc)

To recap, I don't like my solution. It's hacky and ugly. But I haven't come up with anything better yet. I would really like additional suggestions, yours were much appreciated, made me think about things more and realize that it's worse than I had though ;0)
May 15, 2006 at 10:36 AM
originally posted by: austinlamb

I've just found something that may be an approach to this problem. It's new in .NET 2.0 and I just discovered it.

You can not only keep track of network connectivity (via the above methods), but also database connectivity, via the StateChange event on DbConnection (inherited by SqlConnection). See this MSDN2 page for documentation on this event : http://msdn2.microsoft.com/en-US/library/system.data.common.dbconnection.statechange.aspx

So, you could do something like this:

public void DatabaseStuff() {
StateChangeEventHandler changeHandler = new StateChangeEventHandler(dbStateChanged);

using(SqlConnection sqlConn = new SqlConnection(ConnectionString)) {

sqlConn.StateChange += changeHandler;
try {
sqlConn.Open();

....do stuff....

sqlConn.StateChange -= changeHandler;
sqlConn.Close();
}
catch (SqlException ex) {
...do exception handling here...
}
catch (Exception ex) {
...do other exception handling here...
}

}
}

public void dbStateChanged(object sender, StateChangeEventArgs e) {
if(e.CurrentState != ConnectionState.Open)
NotifyThatDatabaseOffline();
}


With that code, if the state of the database changes to something other than open, the event will fire and dbStateChanged() will kick off, which can notify your app that it is offline (via whatever means you are using, EventBroker or whatever). But in this way, you're not relying on just any exception at the database to indicate this - you're relying only on the actual state of the database connection changing.

So if an exception occurs, let's say, due to something going wrong in a stored proc, this won't cause the app to go "offline", which is a good thing.

This is just off the top of my head, the code above may not work, but it's an idea - anybody have any thoughts on this?