{"id":104411,"date":"2020-11-02T07:00:00","date_gmt":"2020-11-02T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=104411"},"modified":"2020-11-02T06:46:56","modified_gmt":"2020-11-02T14:46:56","slug":"20201102-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20201102-00\/?p=104411","title":{"rendered":"How can I ask the networking stack whether the system has obtained network connectivity?"},"content":{"rendered":"<p>Recall a while back we had a customer who <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200415-00\/?p=103673\"> had assumed that the <code>Get\u00adIp\u00adAddr\u00adTable<\/code> function returned the IP addresses sorted by scope rather than by IP address<\/a>. Digging into the customer&#8217;s actual problem revealed that what they really wanted to know was when the system had obtained network connectivity.<\/p>\n<p>Their original plan was to poll on <code>Get\u00adIp\u00adAddr\u00adTable<\/code> expecting their public IP address to show up first, but we learned that that technique was flawed. So what can they do? They wondered if maybe there was a specific service whose startup demonstrated that the system had an IP address.<\/p>\n<p>Network connectivity is more fickle than just checking for a service. It can come and go dynamically. You wander in and out of range of a Wi-Fi base station. You plug in or remove the USB networking adapter. The cleaning crew temporarily\u2014or perhaps permanently\u2014unplugs the Ethernet cable because it prevents them from vacuuming the floor.<\/p>\n<p>The networking folks had a few suggestions. One was to use <code>INetwork\u00adList\u00adManager::<\/code><code>get_<\/code><code>Is\u00adConnected<\/code>, which tells you if the system has any network connectivity at all. This will tell you whether the system is connected to the local network, if that&#8217;s what you care about.<\/p>\n<p>If you are looking for internet connectivity, then you can use <code>INetwork\u00adList\u00adManager::<\/code><code>get_<\/code><code>Is\u00adConnected\u00adTo\u00adInternet<\/code>.<\/p>\n<p>The methods on <code>INetwork\u00adList\u00adManager<\/code> aggregates network connectivity across multiple interfaces, saving you the trouble of having to deal with the messy details of the networking stack.<\/p>\n<p>If you prefer to get your hands dirty, you can use the <code>Notify\u00adUnicast\u00adIp\u00adAddress\u00adChange<\/code> function which lets you register a callback that will be invoked whenever a change occurs to the IP address of the system (optionally filtered to only IPv4 or IPv6).<\/p>\n<p>This function is a little tricky because your callback doesn&#8217;t actually get the address information. Instead, it contains only enough information for you to call <code>Get\u00adUnicast\u00adIp\u00adAddress\u00adEntry<\/code> to obtain more information about the new address. In particular, you want to see if the IP address meets your criteria (routability being one thing you probably want) and that the Duplicate Address Detection (DAD) state is <i>Preferred<\/i>, indicating that this is the preferred IP address.<\/p>\n<p>Another high-level interface is the network connection profile in the Windows Runtime.<\/p>\n<pre>using Windows.Networking.Connectivity;\r\n\r\nvar level = NetworkConnectivityLevel.None;\r\nvar profile = NetworkInformation.GetInternetConnectionProfile();\r\nif (profile != null) {\r\n  level = profile.GetNetworkConnectivityLevel();\r\n}\r\n<\/pre>\n<p>The <code>Get\u00adInternet\u00adConnection\u00adProfile<\/code> method gives you a <code>Connection\u00adProfile<\/code> object which describes the system&#8217;s internet connection. This also tries to distinguish between normal internet connectivity and being trapped in a captive portal. You can subscribe to the <code>Network\u00adStatus\u00adChanged<\/code> event to be notified when the connectivity level changes. (The Windows Runtime class also gives you other information, such as whether you are on a metered network.)<\/p>\n<p>You can see from the extra features in the Windows Runtime class that it is more focused on app scenarios (particularly mobile networking) than on understanding the low-level details of the networking stack. This particular customer was writing software that ran in a server room, so they didn&#8217;t need to worry about things like metered networks or captive portals.<\/p>\n<p>Or at least I hope they didn&#8217;t!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Depends what kind of connectivity you&#8217;re looking for.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-104411","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Depends what kind of connectivity you&#8217;re looking for.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104411","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=104411"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104411\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=104411"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=104411"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=104411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}