Determine if internet connection is available - c#

I know that I am not the first to ask the question: How do I find out if my application is online or not?
I found this post: StackOverflow.
I want to do it with C# and .NET 3.5.
The recommendation is to ping the resource regularly. I am not very happy with that advice. I would rather detect a network change and THEN ping my service to check if it is online.
.NET provides two events for this purpose:
NetworkChange.NetworkAvailabilityChanged
NetworkChange.NetworkAddressChanged
The first event sounds good but it is fired only if the last network card which is online goes offline. I have several virtual network cards which have been installed by VMWare and those are always online.
The second event works but between plugging the network cable and the event, there are often 5 seconds wait time.
The Windows tray icon reacts more or less immediately when I am unplugging the cable.
What is the best way to be as fast as this tray icon?
My workaround would be to poll
NetworkInterface.GetAllNetworkInterfaces()
every 500ms and to throw my own event in case that the status of a network adapter changed.
There must be a better solution :)

I tried the link the Webleeuw suggested, but that code also needs between 4 and 10 seconds to notify me when I plug or unplug my cable.
Now, I wanted to know if it just my computer or installation and I wrote my own Observer class which is based on NetworkInterface.GetAllNetworkInterfaces().
And: It works with lightning speed. My app reacts now as quickly as does the tray.
The code is far from production code, it is just a quick hack. But this is what I will build upon now :)
using System;
using System.Net.NetworkInformation;
using Timer=System.Threading.Timer;
namespace NetworkCheckApp
{
public class NetworkStatusObserver
{
public event EventHandler<EventArgs> NetworkChanged;
private NetworkInterface[] oldInterfaces;
private Timer timer;
public void Start()
{
timer = new Timer(UpdateNetworkStatus, null, new TimeSpan(0, 0, 0, 0, 500), new TimeSpan(0, 0, 0, 0, 500));
oldInterfaces = NetworkInterface.GetAllNetworkInterfaces();
}
private void UpdateNetworkStatus(object o)
{
var newInterfaces = NetworkInterface.GetAllNetworkInterfaces();
bool hasChanges = false;
if (newInterfaces.Length != oldInterfaces.Length)
{
hasChanges = true;
}
if (!hasChanges)
{
for (int i = 0; i < oldInterfaces.Length; i++)
{
if (oldInterfaces[i].Name != newInterfaces[i].Name || oldInterfaces[i].OperationalStatus != newInterfaces[i].OperationalStatus)
{
hasChanges = true;
break;
}
}
}
oldInterfaces = newInterfaces;
if (hasChanges)
{
RaiseNetworkChanged();
}
}
private void RaiseNetworkChanged()
{
if (NetworkChanged != null)
{
NetworkChanged.Invoke(this, null);
}
}
}
}

Try this using NetworkChange class
using System.Net.NetworkInformation
private void Form5_Load(object sender, EventArgs e)
{
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
}
private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
if (e.IsAvailable)
{
MessageBox.Show("Available");
}
else
{
MessageBox.Show("Not available");
}
}

People here already told it but there is a diference between network availability and internet availability.
You can have network availability between your network interface and local router but havent internet availability between your local router and your Internet Service Provider (ISP).
There is another problem that testing by ping will tell you about internet availability but not about what network interface is providing it, i think the only way is force ping throught one interface but it isnot possible on windows.

Pinging your resource regularly is the only option that will give you a notification if the service goes offline, as well as if the client goes offline. Potentially you want to handle both situations.

The windows tray icon is very likely connected to the network card drivers, i.e. below the operating system level which is why it can react so fast.
Since the network card is only one of many links between your client and the service that it accesses on the Internet, the only reliable way to detect whether or not the Internet is available is to poll some service out on the Internet, much the same way that ping does. In TCP/IP networking, this is known as a keepalive, and many protocols will have this built into them as an option.

About the pinging: depending on how you wish to interpret the results, pinging doesn't seem watertight to me. What if the target times out once in a while, while the connection remains alive? I have yet to see the server that never fails to respond to a ping.
Checking every X millis if the network interface is still online (NetworkInterface.OperationalStatus property) seems more reliable if you'd ask me.
EDIT: This article deals with network address events on a lower level than the System.Net.NetworkInformation.NetworkChange class, or so it seems. On my pc it works very fast, so hopefully you'll be able to use that solution.

You can use ping, but I would also build a simple call to return a "yes" if it is online. That way you do know if the server is up and that it is running your code. Also I would only call or ping when a network resource is needed and not continually.

Doing a ping is definitely not the cleanest option, especially if it is a web server. Some hosts will disable response to ICMP traffic, so you may ping but not get a response. How about just handling the exception gracefully when it occurs?

Related

How to check PC is connected with Internet or Intranet without IP address and Ping method in C#?

How can I check PC is Connected with Intranet or Internet without using Ping method and IP address in C#?
For my use case, I needed to have a service up in a LAN network and check Network status from time to time. I eventually used this:
static readonly INetworkListManager NetworkListManager = new NetworkListManager();
// ...
while (NetworkListManager.IsConnected) {
// do something...
}
// loop is over. no internet!
while (!NetworkListManager.IsConnected) {
// wait for reconnection...
}
In my case that achieved what I needed, and with some testing it also worked on my WAN environment. But as always, there's no 100% correct assumption when it comes to interacting with other hardware. Incorrect result can happen, so put in as much as test you can.
Here's something i used for a game of mine to detect if there is a network connection without it even touching or talking the router or other devices:
// Recommended for clean code
public static bool InternetConnection() => System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
The code above is just the same as:
public static bool InternetConnection() {
return System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable();
}

TCPClient & Sockets failing to connect to the Server

I have a very strange problem with my connection to a server on a TCPListener/TCPClient basis. At some point during testing I am unable to connect to my server-application anymore, every try it times out. Netstats on both sides show, that my application listens on the right port, and the client is trying to connect to the right ip and port, but it does not advance further than "SYN_SENT". The server just displays "LISTENING" all the time. All I can do is restart my PC, which temporarily fixes this problem. But after some connections, it starts all over again.
Up to now I tested TCPClient and Sockets class to connect to the server but both show this behaviour, what is not surprising, as TCPClient is a wrapper around the Sockets Class afaik.
Firewall is checked on both sides, things like Remote Desktop work perfectly fine, and is not blocking the Connection of my Application. There are no connections left to close or something, already cheked everything I know (maybe not that much ;) )
So whats the problem?
Edit:
A Method that needs to connect to my Server:
public int GetSomeDataFromServer(string blargh)
{
int ret;
try
{
using(ConnectionTCPStream ctp = new ConnectionTCPStream())
{
if(ctp.EstSecConnWithServ())
{
ret = CKSHandler(ctp, blargh);
}
else
{ ret = (int)ErrFlags.ServerDeniedConnection; }
}
return ret;
}
catch(Exception)
{
InternalError = ErrFlags.ServerUnreachable;
return (int)ErrFlags.ServerUnreachable;
}
}
The Constructor of my Class that is dealing with the Connections:
public ConnectionTCPStream()
{
Client = new TcpClient("VeryImportantAdress", 49778); //it fails right here!
rsaCrypt = new RSACH() { RSAForeignPubKey = "An 8192-Bit long RSA Public key." };
AESPASS = AESThenHMAC.CreatePassword(200);
}
Sounds like you are using up all your connections or some other resource.
What do you see when you do a netstat -an ? Do you see a bunch of open ports?
There an Article Here that could possibly help you here
Some other resource may be killing you, might be worth having an SA fire up a resource monitor to check the health of the host when you run into this situation.
If there's no errors being thrown, it makes your life that much harder. The problem typically happens when you don't cleanly clean up your socket disconnects.
The answer is the firewall which changed its mind every now and then. I couldn't test that before because i had no access to it. Now i have changed settings while i had this blockade and it worked fine again. So the answer is: Always have access to the firewall and don't forget to check it.

Process launcher launching process inside of a windows service but the application window is not opening [duplicate]

I currently have a single application that needs to be started from a windows service that i am coding in .net 3.5. This application is currently running as the user who ran the service, in my case the SYSTEM user. If running as the SYSTEM user it does not show the application to the users desktop. Thoughts? advice?
//constructor
private Process ETCHNotify = new Process();
//StartService()
ETCHNotify.StartInfo.FileName = baseDir + "\\EtchNotify.exe";
ETCHNotify.StartInfo.UseShellExecute = false;
//BackgroundWorkerThread_DoWork()
if (!systemData.GetUserName().Equals(""))
{
// start ETCHNotify
try {
ETCHNotify.Start();
}
catch (Exception ex)
{
systemData.Run("ERR: Notify can't start: " + ex.Message);
}
}
I only execute the try/catch if the function i have written GetUserName() (which determines the username of the user running explorer.exe) is not null
again to reiterate: desired functionality is that this starts ETCHNotify in a state that allows it to interact with the currently logged in user as determined by GetUserName()
Collage of some post found around (this and this)
Note that as of Windows Vista, services are strictly forbidden from interacting directly with a user:
Important: Services cannot directly interact with a user as of Windows
Vista. Therefore, the techniques mentioned in the section titled Using
an Interactive Service should not be used in new code.
This "feature" is broken, and conventional wisdom dictates that you shouldn't have been relying on it anyway. Services are not meant to provide a UI or allow any type of direct user interaction. Microsoft has been cautioning that this feature be avoided since the early days of Windows NT because of the possible security risks.
There are some possible workarounds, however, if you absolutely must have this functionality. But I strongly urge you to consider its necessity carefully and explore alternative designs for your service.
Use WTSEnumerateSessions to find the right desktop, then CreateProcessAsUser to start the application on that desktop (you pass it the handle of the desktop as part of the STARTUPINFO structure) is correct.
However, I would strongly recommend against doing this. In some environments, such as Terminal Server hosts with many active users, determining which desktop is the 'active' one isn't easy, and may not even be possible.
A more conventional approach would be to put a shortcut to a small client app for your service in the global startup group. This app will then launch along with every user session, and can be used start other apps (if so desired) without any juggling of user credentials, sessions and/or desktops.
Ultimately in order to solve this i took the advice of #marco and the posts he mentioned. I have created the service to be entirely independent of the tray application that interacts with the user. I did however install the Tray application via registry 'start up' methods with the service. The Service installer will now install the application which interacts with the user as well... This was the safest and most complete method.
thanks for your help everyone.
I wasn't going to answer this since you already answered it, (and it's oh, what? going on 2.5 years OLD now!?) But there are ALWAYS those people who are searching for this same topic, and reading the answers...
In order to get my service to Interact with the Desktop, no matter WHAT desktop, nor, how MANY desktops, nor if the service was even running on the SAME COMPUTER as the desktop app!! None of that matters with what I got here... I won't bore you with the details, I'll just give you the meat and potatoes, and you and let me know if you want to see more...
Ok. First thing I did was create an Advertisement Service. This is a thread that the service runs, opens up a UDP socket to listen for broadcasts on the network. Then, using the same piece of code, I shared it with the client app, but it calls up Advertise.CLIENT, rather than Advertise.SERVER... The CLIENT opens the port I expect the service to be on, and broadcasts a message, "Hello... Is there anybody out there??", asking if they're there ANY servers listening, and if so, reply back to THIS IP address with your computer name, IP Address and port # where I can find the .NET remoting Services..." Then it waits a small amount of time-out time, gathers up the responses it gets, and if it's more than one, it presents the user with a dialog box and a list of services that responded... The Client then selects one, or, if only ONE responded, it will call Connect((TServerResponse) res); on that, to get connected up. At this point, the server is using Remoting Services with the WellKnownClientType, and WellKnownServerType to put itself out there...
I don't think you are too interested in my "Auto-Service locater", because a lot of people frown on UDP, even more so when your app start broadcasting on large networks. So, I'm assuming you'd be more interested in my RemotingHelper, that gets the client connected up to the server. It looks like this:
public static Object GetObject(Type type)
{
try {
if(_wellKnownTypes == null) {
InitTypeCache();
}
WellKnownClientTypeEntry entr = (WellKnownClientTypeEntry)_wellKnownTypes[type];
if(entr == null) {
throw new RemotingException("Type not found!");
}
return System.Activator.GetObject(entr.ObjectType, entr.ObjectUrl);
} catch(System.Net.Sockets.SocketException sex) {
DebugHelper.Debug.OutputDebugString("SocketException occured in RemotingHelper::GetObject(). Error: {0}.", sex.Message);
Disconnect();
if(Connect()) {
return GetObject(type);
}
}
return null;
}
private static void InitTypeCache()
{
if(m_AdvertiseServer == null) {
throw new RemotingException("AdvertisementServer cannot be null when connecting to a server.");
}
_wellKnownTypes = new Dictionary<Type, WellKnownClientTypeEntry>();
Dictionary<string, object> channelProperties = new Dictionary<string, object>();
channelProperties["port"] = 0;
channelProperties["name"] = m_AdvertiseServer.ChannelName;
Dictionary<string, object> binFormatterProperties = new Dictionary<string, object>();
binFormatterProperties["typeFilterLevel"] = "Full";
if(Environment.UserInteractive) {
BinaryServerFormatterSinkProvider binFormatterProvider = new BinaryServerFormatterSinkProvider(binFormatterProperties, null);
_serverChannel = new TcpServerChannel(channelProperties, binFormatterProvider);
// LEF: Only if we are coming form OUTSIDE the SERVICE do we want to register the channel, since the SERVICE already has this
// channel registered in this AppDomain.
ChannelServices.RegisterChannel(_serverChannel, false);
}
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IPawnStatServiceStatus)));
RegisterType(typeof(IPawnStatServiceStatus),m_AdvertiseServer.RunningStatusURL.ToString());
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IPawnStatService)));
RegisterType(typeof(IPawnStatService), m_AdvertiseServer.RunningServerURL.ToString());
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IServiceConfiguration)));
RegisterType(typeof(IServiceConfiguration), m_AdvertiseServer.RunningConfigURL.ToString());
}
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration, RemotingConfiguration=true)]
public static void RegisterType(Type type, string serviceUrl)
{
WellKnownClientTypeEntry clientType = new WellKnownClientTypeEntry(type, serviceUrl);
if(clientType != RemotingConfiguration.IsWellKnownClientType(type)) {
RemotingConfiguration.RegisterWellKnownClientType(clientType);
}
_wellKnownTypes[type] = clientType;
}
public static bool Connect()
{
// Init the Advertisement Service, and Locate any listening services out there...
m_AdvertiseServer.InitClient();
if(m_AdvertiseServer.LocateServices(iTimeout)) {
if(!Connected) {
bConnected = true;
}
} else {
bConnected = false;
}
return Connected;
}
public static void Disconnect()
{
if(_wellKnownTypes != null) {
_wellKnownTypes.Clear();
}
_wellKnownTypes = null;
if(_serverChannel != null) {
if(Environment.UserInteractive) {
// LEF: Don't unregister the channel, because we are running from the service, and we don't want to unregister the channel...
ChannelServices.UnregisterChannel(_serverChannel);
// LEF: If we are coming from the SERVICE, we do *NOT* want to unregister the channel, since it is already registered!
_serverChannel = null;
}
}
bConnected = false;
}
}
So, THAT is meat of my remoting code, and allowed me to write a client that didn't have to be aware of where the services was installed, or how many services were running on the network. This allowed me to communicate with it over the network, or on the local machine. And it wasn't a problem to have two or more people running the app, however, yours might. Now, I have some complicated callback code in mine, where I register events to go across the remoting channel, so I have to have code that checks to see if the client is even still connected before I send the notification to the client that something happened. Plus, if you are running for more than one user, you might not want to use Singleton objects. It was fine for me, because the server OWNS the objects, and they are whatever the server SAYS they are. So, my STATS object, for example, is a Singleton. No reason to create an instance of it for EVERY connection, when everyone is going to see the same data, right?
I can provide more chunks of code if necessary. This is, of course, one TINY bit of the overall picture of what makes this work... Not to mention the subscription providers, and all that.
For the sake of completeness, I'm including the code chunk to keep your service connected for the life of the process.
public override object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if(lease.CurrentState == LeaseState.Initial) {
lease.InitialLeaseTime = TimeSpan.FromHours(24);
lease.SponsorshipTimeout = TimeSpan.FromSeconds(30);
lease.RenewOnCallTime = TimeSpan.FromHours(1);
}
return lease;
}
#region ISponsor Members
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
public TimeSpan Renewal(ILease lease)
{
return TimeSpan.FromHours(12);
}
#endregion
If you include the ISponsor interface as part of your server object, you can implement the above code.
Hope SOME of this is useful.
When you register your service, you can tell it to allow interactions with the desktop. You can read this oldie link http://www.codeproject.com/KB/install/cswindowsservicedesktop.aspx
Also, don't forget that you can have multiple users logged in at the same time.
Apparently on Windows Vista and newer interacting with the desktop has been made more difficult. Read this for a potential solution: http://www.codeproject.com/KB/cs/ServiceDesktopInteraction.aspx

Why GetIsNetworkAvailable() method always returning value as true with vpn client reconnecting? [duplicate]

I have this method:
public static void testConnection()
{
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
System.Windows.MessageBox.Show("This computer is connected to the internet");
}
else
{
System.Windows.MessageBox.Show("This computer is not connected to the internet");
}
}
I suppose it would tell me whether the connection is available or not but it always return true (and print the 1st message) even when I'm sure there is no connection. What I'm doing wrong?
P.S.: I'm still learning C#.
I think this method is more appropriate:
public static bool getIsInternetAccessAvailable()
{
switch(NetworkInformation.GetInternetConnectionProfile().GetNetworkConnectivityLevel())
{
case NetworkConnectivityLevel.InternetAccess:
return true;
default:
return false;
}
}
Please correct me if I am wrong but as far as I can see the method you are using is checking network connectivity and not necessarily internet connectivity. I would assume if you are on a network of any sort this would return true regardless of the internet being available or not? See this.
I have noticed that one way of checking for internet connectivity is as follows:
private bool IsInternetAvailable()
{
try
{
Dns.GetHostEntry("www.google.com"); //using System.Net;
return true;
} catch (SocketException ex) {
return false;
}
}
The above code can be found (in VB.Net by reading the comment from Joacim Andersson [MVP]) in the following post.
Note: The latest edit was suggested by AceInfinity but was rejected in community review. My reputation is too low to override this so I made the change myself.
Note that we are using the Windows.Networking.Connectivity.NetworkInformation and not the System.Net.NetworkInformation namespace.
public bool checkInternetAccess()
{
var connectivityLevel = Windows.Networking.Connectivity.NetworkInformation
.GetInternetConnectionProfile().GetNetworkConnectivityLevel();
return connectivityLevel == NetworkConnectivityLevel.InternetAccess;
}
Basically what ventura8 said. I would comment his solution, mentioning the namespaces, but I lack enough reputation.
From msdn:
There are many cases in which a device or computer is not connected to
a useful network but is still considered available and
GetIsNetworkAvailable will return true.
One of these examples could be your case:
For example, if the device
running the application is connected to a wireless network that
requires a proxy, but the proxy is not set, GetIsNetworkAvailable will
return true. Another example of when GetIsNetworkAvailable will return
true is if the application is running on a computer that is connected
to a hub or router where the hub or router has lost the upstream
connection.
From MSDN (emphasis is mine):
A network connection is considered to be available if any network interface is marked "up" and is not a loopback or tunnel interface.
If with "connection" you mean Internet connection then you should DllImport the function InternetCheckConnection or InternetQueryOption.
Instead if what you need is just to know if computer is connected to any useful LAN the best thing you can do is to iterate network connection by yourself and to filter (using NetworkInterfaceType, IsReceiveOnly and OperationalStatus) what you're not interested too.
I suppose it would tell me whether the connection is available or not but it always return true (and print the 1st message) even when I'm sure there is no connection.
You have a different opinion on the meaning of 'connection' than the manual does. As far as the operating system is concerned, you have a connection when there is a patched ethernet cable connected to your NIC, or when your wireless card is connected to an wireless access point, or any connection is active.
The manual also explains this:
NetworkInterface.GetIsNetworkAvailable:
Indicates whether any network connection is available.
If you want to detect internet connectivity, take a look at the InternetGetConnectedState() (or InternetCheckConnection(), to check for accessibility of a specific host) methods from the WinINet API.

in c#.net how to send message to remote computer throught internet?

c#.net framework 4.0 client profile,Windows application..
i am developing a game which needs to send its current movements of the game through internet to remote computer where the same application(game) is installed.In Same way current movements of the game of remote computer should be send back...
How this could be possible ?
All the answers so far are using a TCP based approach. If you need high performance and low latency then you might find it better to use UDP instead.
TCP brings a lot of overhead with it to guarantee that packets will be resent if they are lost (and various other bits of functionality). UDP on the other hand leaves it up to you to deal with packets not arriving. If you have a game where losing the odd update isn't important you can achieve far better bandwidth use, latency and scalability by using UDP instead of TCP.
UDP still leaves you with all the issues of firewalls, security etc though.
If you need to have it work without worrying about firewalls being an issue then you want to choose a solution that uses HTTP over port 80.
To do that you need to implement a client-server behavior through TCP/IP
There are very different ways to do this
This code I've written could give you a start (it's an option, but not the only one, I leave it off to you to choose the method that suits you best)
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
static class ServerProgram
{
[STAThread]
static void Main()
{
ATSServer();
}
static void ATSServer()
{
TcpChannel tcpChannel = new TcpChannel(7000);
ChannelServices.RegisterChannel(tcpChannel);
Type commonInterfaceType = Type.GetType("ATSRemoteControl");
RemotingConfiguration.RegisterWellKnownServiceType(commonInterfaceType,
"RemoteATSServer", WellKnownObjectMode.SingleCall);
}
}
public interface ATSRemoteControlInterface
{
string yourRemoteMethod(string parameter);
}
public class ATSRemoteControl : MarshalByRefObject, ATSRemoteControlInterface
{
public string yourRemoteMethod(string GamerMovementParameter)
{
string returnStatus = "GAME MOVEMENT LAUNCHED";
Console.WriteLine("Enquiry for {0}", GamerMovementParameter);
Console.WriteLine("Sending back status: {0}", returnStatus);
return returnStatus;
}
}
class ATSLauncherClient
{
static ATSRemoteControlInterface remoteObject;
public static void RegisterServerConnection()
{
TcpChannel tcpChannel = new TcpChannel();
ChannelServices.RegisterChannel(tcpChannel);
Type requiredType = typeof(ATSRemoteControlInterface);
//HERE YOU ADJUST THE REMOTE TCP/IP ADDRESS
//IMPLEMENT RETRIEVAL PROGRAMATICALLY RATHER THAN HARDCODING
remoteObject = (ATSRemoteControlInterface)Activator.GetObject(requiredType,
"tcp://localhost:7000/RemoteATSServer");
string s = "";
s = remoteObject.yourRemoteMethod("GamerMovement");
}
public static void Launch(String GamerMovementParameter)
{
remoteObject.yourRemoteMethod(GamerMovementParameter);
}
}
Hope this Helps.
You should look into some middleware teknologies like WCF, Web service
this is object oriented and easy to develop when you first get the hang of it
You have a lot to consider for this.
You will need to think about security, firewall issues etc.
If that is all put to one side, then you can set up a tcp socket server / client approach.
A quick google will yield plenty of examples.
Check out the Microsoft example http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx
What have you tried?
You can use the System.Net and System.Net.Sockets namespaces to send TCP packets.

Categories