czwartek, 12 kwietnia 2012

Notatki o Windows 8 Consumer Preview - odc. 10

Tym razem postaram się streścić w kilku zdaniach całkiem sporą dawkę nowych ciekawych informacji na temat aplikacji utrzymujących cały czas łączność z siecią, nawet wtedy gdy się nie wykonują lub gdy system Windows 8 sprawia wrażenie wyłączonego, a precyzyjniej gdy jest w stanie “Connected Standby” (uśpienie z dostępem do sieci, o tym wprowadzonym w Windows 8 stanie można więcej się dowiedzieć choćby oglądając sesję Understanding Connected Standby z konferencji BUILD, nie licząć różnych artykułów w sieci). Mamy możliwość napisania własnej aplikacji do prowadzenia rozmów tekstowych i VoIP czy klienta pocztowego powiadamiającego o przychodzących mailach.

Sporą zmianą jest podejście do koncepcji notyfikacji push typu raw. O ile w Windows Phone 7 mogą być odbierane tylko przez działającą aplikację (jako foreground), o tyle w Windows 8 notyfikacje raw mogą uruchamiać taska wykonującego się w tle! Służy ku temu dedykowany rodzaj triggera. Wprowadzono pojęcie aplikacji lock-screen (jak wiadomo z wcześniejszej wersji takie aplikacje zawierają taski wykonujące się w tle). O ile notyfikacje tile, badge, toast mogą też być odbierane przez wszystkie aplikacje, o tyle notyfikacje raw są zastrzeżone jedynie dla aplikacji lock-screen. Za pomocą notyfikacji raw możemy wysyłać maksymalnie 5kB danych.

Scenariusze real-time uzyskujemy

  • korzystając z notyfikacji push aktualizujących kafelki, wyświetlających notyfikacje na ekranie lub uruchamiających kod z tle. Mamy tu WNS (Windows Notification Service) z utrzymywanym przez system ciągłym połączeniem. Zyskujemy wydajność - jedno połączenie obsługuje wiele aplikacji, nie obciążamy naszego serwera trzymanymi połączeniami, nie wysyłamy keep-alive pomiędzy naszym serwerem i klientem - oraz w wielu przypadkach prostotę - nie musimy pisać tasków w tle chyba że użyjemy notyfikacji raw. Aczkolwiek potrzebujemy dostępu do Internetu, mogą być problemy z firewallami, nie mamy gwarancji dostarczenia, nie każdy protokół da się opakować w WNS np. Microsoft Exchange, czasami chcemy zachować prywatność wysyłanych powiadomień i czasami lepiej jest wybrać inny sposób lub zastosować ich kombinację.
  • za pomocą network triggera, który potrafi wywoływać kod w tle w momencie przyjścia danych lub pakietu keep-alive. Mamy tutaj gwarancję odbioru, ponieważ jest utrzymywane połączenie pomiędzy naszym serwerem i klientem. Mamy kompatybilność z istniejącymi protokołami wymagającymi trwałego połączenia. Z drugiej strony to podejście jest bardziej złożone, mamy też ograniczenie do 5 network triggerów w aplikacji.
  • za pomocą triggera czasowego lub triggerów systemowych. Korzystając z time triggera możemy np. sprawdzać czy nie ma nowych maili na serwerze pocztowym co jakiś okres (minimum 15 minut). Eventy systemowe również może być przydatne - np. gdy w momencie zalogowania się do systemu użytkownika chcielibyśmy, aby w naszej aplikacji zostały pobrane przeznaczone dla niego wiadomości.

Wywoływanie kodu przez trigger dla notyfikacji push typu raw oraz przez network trigger nie jest wspierane przez aplikacje napisane w Java Script! W tym przypadku musi to być C#, VB.NET lub C++.

Aplikacja przypięta do zablokowanego ekranu może prezentować użytkownikowi informacje poprzez zmianę zawartości kafelka (tile) lub znajdującego się na nim znaczka (badge) albo poprzez wyświetlenie notyfikacji na ekranie (on-screen notication). Do zablokowanego ekranu użytkownik może przypiąć maksymalnie 7 aplikacji. Aplikacja poprzez API może poprosić użytkownika o przypięcie (dostajemy status mówiący o tym czy mamy pozwolenie i jaki jego rodzaj - z komunikacją real-time czy bez niej), można ją też dodać lub usunąć poprzez sekcję Personalize w ustawieniach, wreszcie system z uwagi na małą liczbę zasobów może usunąć aplikację z zablokowanego ekranu.

Są dwa rodzaje network triggera:

  • push notification – reakcja na przyjście danych do socketu, nawet jeśli aplikacja jest uśpiona
  • keep-alive – wysyłanie pakietów keep-alive przez uśpioną aplikację, aby serwer nie zamknął połączenia

Aplikacja lock-screen korzystająca z network triggera musi korzystać z obu rodzajów.

Dla network triggera możemy wyróżnić dwa typy zasobów - tzw. sloty software i hardware. Domyślnym typem jest software, wtedy trigger nie zadziała, gdy system będzie w stanie Connected Standby. Slot hardware zapewnia działanie triggera także w tym stanie! Aczkolwiek slot hardware mają tylko urządzenia sprzętowo przystosowane do obsługi trybu Connected Standby. Użycie network triggerów ze slotami hardware zostało dodatkowo ograniczone - trzy pierwsze aplikacje, które zarejestrują się na typ hardware mają możliwość używania trzech triggerów z tym rodzajem slotów. Pozostałe aplikacje mają do dyspozycji tylko typ software.

BTW triggery nie działają przy stanie hibernacji, uśpienia systemu oraz jak jest wyłączony.

Jeśli nasza aplikacja “zaobserwuje” dużo zrywanych połączeń, możemy wywołać w niej metodę triggera sieciowego o nazwie DecreaseNetworkKeepAliveInterval. Nie należy jej nadużywać, ale dzięki niej możemy wymusić, aby system skrócił okres keep-alive dla danego kanału.

Możemy również odczytać bieżącą wartość keep-alive przyjętą przez system, co w niektórych przypadkach może być przydatne.

Na koniec kilka nowych uwag o testowaniu i debugowaniu komunikacji sieciowej. Z uwagi na izolację godny odnotowania jest fakt, że komunikacja sieciowa między różnymi procesami z adresem loopback jest zablokowana. Aczkolwiek w celach testowych za pomocą odpowiednich narzędzi możemy nadać (lub odebrać) pozwolenie na komunikację z adresem loopback dla danej aplikacji. Visual Studio 11 automatycznie przydziela takie uprawnienie.

Niejako przy okazji mamy podane miejsce w rejestrze, gdzie zapisywany jest identyfikator aplikacji.

 

How to set background connectivity options

Lifecycle model for Metro style apps

This new model provides a mechanism for apps that must work in the background (such as Voice over Internet Protocol (VoIP), instant messaging (IM), and email) to provide an always-connected experience for the end user. This means that an app that depends on a long-running connection to a remote endpoint server can still work when the app is suspended.

In order to enable real-time networking scenarios for a Metro style app that needs to be always connected, several new features have been introduced:

  • Windows Push Notification Services (WNS)
  • Background tasks
  • System trigger for session start
  • Time triggers
  • Push notification triggers (raw push notifications)
  • Network triggers

These features provide support for always connected apps that need to receive incoming network packets or raw push notifications when a Metro style app is suspended.

Other background tasks features can also be used by a network app. Some other triggers available for use by a Metro style app include the following:

  • Maintenance triggers (periodic time events for maintenance)
  • System triggers for users and sessions (user session connected/disconnected, user present/away, and online ID change)
  • System triggers for networking status (network state change, internet available/not available)
  • System triggers for lock screen (app add/remove)

A time trigger could be used when an app does not require real-time connectivity but needs to run for a brief time at some interval. A system trigger could be used when the app needs to be aware of events (for example, the availability of Internet connectivity or user presence).

Once a Metro app is suspended, any existing network connections are closed and incoming network packets are dropped. To be always connected, an app also needs to be a lock screen app. A lock screen app is a special type of app that can display notifications on the lock screen and run code in the background when the app is not in the foreground. Only apps that use one or more background tasks may be lock screen apps.

Lock screen apps have some special abilities:

  • Able to receive a raw push notification from WNS that can run code when the notification is received.
  • Able to maintain a persistent transport connection in the background to a remote service and run code when data or a keepalive packet is received using the network trigger features.
  • Able to run code when a time trigger occurs.
  • Able to run code when a user session is started.

Apps pinned to the lock screen can present information to the user when in the background by updating and displaying a badge icon on the lock screen when there is new information. These apps can also display an on-screen notification when a message arrives. If the notification is tapped or clicked, the user is asked to unlock the device. When the device is unlocked, the app corresponding to the notification is launched with context information.

A user can have a maximum of seven lock screen apps at any given time. A user can add or remove an app from the lock screen at any time. If the system runs short on resources, the system can also remove an app from the lock screen.

Several mechanisms discussed below can be used to enable real-time scenarios for apps that are placed on the lock screen. Each has its benefits and tradeoffs. The mechanisms are not mutually exclusive and can be combined in some apps.

Using WNS in Metro style apps

WNS is a cloud service hosted by Microsoft for Windows 8 that can be used by Metro style apps to receive notifications that can execute code, update a live tile, or raise an on-screen notification. In order to use WNS, the local computer must be connected to the Internet so that the WNS service can communicate with it.

When a push notification is delivered to a lock screen app, the app can run code in response to the notification. WNS use can be more power efficient than using network trigggers.

WNS offers a number of benefits:

  • WNS offers the most power-efficient mechanism for delivering real-time notifications to lock screen apps.
  • WNS simplifies the developer model for your app. In most scenarios, developers do not have to write any background tasks, because the operating system renders the tiles or toast. In a small subset of scenarios, if your app must run a background task, it need only register the raw trigger and the background task itself.
  • No persistent socket connection needs to be maintained between the client app and a remote server because Windows maintains the connection to WNS. As a result, the overhead of sending keep-alive messages is not required.
  • A single WNS connection between the client and the cloud service can support all apps on the local computer, which translates to potential battery life efficiency for the client.
  • Cost is reduced on the server side because there is no need to maintain many parked TCP socket connections.
  • The operational cost for your service may be lower, because there is no parked connection between the client and the remote service.
  • Your app does not have to reside in memory at all times, because it can be terminated and still have WNS update the tile, raise a toast, or trigger a background task to run upon receipt of an incoming raw notification.
  • Background tasks that do not use raw push notifications can be written in JavaScript, C#, VB.NET, and C++. The network trigger feature and raw push notifications are not available in JavaScript.

WNS can also be blocked by some network firewalls even when Internet access is available.

Given the advantages, we recommend that developers who build VoIP, IM, or email apps consider using WNS notifications for lock screen apps, but consider alternatives if they do not meet your requirements.

There is no need to build a lock screen app if you simply want to have a live tile update or raise a toast using WNS. A lock screen app is required while using WNS only when the app requires a raw push notification to trigger a background task to run.

Using network triggers in Metro style apps

The System.Net.Sockets.ControlChannelTrigger class implements the network trigger feature available for apps that must maintain a persistent transport connection in the background. This is typically needed for connectivity to servers running an older protocol that cannot be modified to use WNS, or when there are concerns about privacy or message service-level agreements (SLAs).

For example, an email client that uses a Microsoft Exchange server and is deployed widely within an enterprise cannot be modified to use WNS to send notifications when an email message arrives. The client must maintain a direct TCP connection to the Microsoft Exchange server.

The ControlChannelTrigger class can be used by instances of the following classes in the Windows.Networking.Sockets that establish a TCP connection:

The ControlChannelTrigger class can also be used by instances of the following that establish a TCP connection:

  • The HttpClient and HttpClientHandler classes in the System.Net.Http namespace in the .NET Framework 4.5. Custom classes that derive from these classes are also supported.
  • The IXMLHTTPRequest2 interface. The IXMLHTTPRequest2 interface is an extension to XMLHttpRequest object defined in several working drafts published by the World Wide Web Consortium (W3C)

The network trigger feature offers a number of benefits:

  • Compatibility with existing client/server protocols that require persistent transport connections.
  • Message delivery guarantees, because the app maintains connection state between the client and the server.

There are also some drawbacks with using the network trigger feature:

  • Using the network trigger feature is more complex than WNS because it requires additional components to maintain the transport connection.
  • An app is limited to a maximum of five network triggers.
  • Apps using the network trigger feature with other background tasks need to be written in C# , VB.NET, or C++.

    Note The ControlChannelTrigger class and related classes are not supported in a Metro style app using JavaScript.

Using time triggers or system event triggers in Metro style apps

Lock screen apps can be configured to run code periodically using a time trigger with a minimum interval of 15 minutes. One example is needing to poll for new e-mail messages, possibly when an app is connected to a POP3 or IMAP email server.

Lock screen apps can also use a system event trigger to run code when the user logs on to the local computer (system trigger for session start). One example is signing in the user in to an instant message service when they start a user session, so instant messages can be received.

Creating a lock screen app

You must set the appropriate capabilities in the app manifest so that your app requests to be placed on the lock screen. Your app must also include code to request to be added to the lock screen.

To get onto the lock screen, an app must get consent from the user. The consent prompt appears when the lock screen request API is called. If the user does not give your app permission to run on the lock screen, then you will not be able to prompt for permission again. However, if the user accidently dismisses the dialog you will be able to prompt again.

If users denies your app permission to be a lock screen app, they can add the app to the lock screen at a later time via the system permissions fly-out for your app. Users can also manually add your app to the lock screen from the Personalize section of PC settings.

Register to become a lock screen app

Ensure that your app’s tile has a wide logo associated with it in the app manifest. Ensure that the app manifest has set the WideLogo attribute on the DefaultTile element. Under <VisualElements>:

<DefaultTile ShowName="allLogos" WideLogo="images\tile.png" />

Indicate your app's intention to use a background task. The app manifest must also specify the executable file that contains the background task and the class name where the entry point of the baskground task is implemented.

If you are building a lock screen app that uses push notifications with WNS, specify the pushNotification background task type. This will ensure that your app will receive WNS push notifications.

If you are building a lock screen app that uses the network trigger feature, specify the realTimeCommunication background task type. This will ensure that your app will receive network trigger notifications.

<Extensions> <Extension Category="windows.backgroundTasks" Executable="$targetnametoken$.exe" EntryPoint="Background.RawPushNotifyTask"> <BackgroundTasks> <Task Type="pushNotification" /> </BackgroundTasks> </Extension> <Extension Category="windows.backgroundTasks" Executable="$targetnametoken$.exe" EntryPoint="Background.ReceivePacketTask"> <BackgroundTasks> <Task Type="controlChannel" /> </BackgroundTasks> </Extension> </Extensions>

Since your app will be on the lock screen, it must also have a lock screen icon that can be used to display missed notifications. To enable this, update your app manifest to include the LockScreen element.

<LockScreen Notification="badge" BadgeLogo="Images\badgelogo.png" />

The Background.BackgroundExecutionManager.RequestAccessAsync methods present the user with a dialog box that requests that an app be added to the lock screen. If the user approves the request, your app can run in the background and place notifications on the lock screen.

bool lockScreenAdded = false; async void ClientInit() { // Lock screen is required to let in-process RealTimeCommunication related // background code to execute. // if (lockScreenAdded == false) { BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync(); Diag.DebugPrint("Lock screen status" + status); switch (status) { case BackgroundAccessStatus.AllowedWithRealTimeConnectivity: // // App is allowed to use RealTimeConnection broker // functionality even in low power mode. // lockScreenAdded = true; break; case BackgroundAccessStatus.AllowedWithoutRealTimeConnectivity: // // App is allowed to use RealTimeConnection broker // functionality but not in low power mode. // lockScreenAdded = true; break; case BackgroundAccessStatus.Denied: // // App should switch to polling mode (example: poll for email based on time triggers) // Diag.DebugPrint("As Lockscreen status was Denied, App should switch to polling mode such as email based on time triggers."); break; } } return; }

If you are building a WNS-based lock screen app, the BackgroundAccessStatus for your app will be set to allowedWithoutRealtimeConnectivity after permission has been granted. The real-time connectivity option is used for network trigger feature and does not affect WNS-based lock screen apps.

If you are building a lock screen app using the network trigger feature, the BackgroundAccessStatus for your app will be set to allowedWithRealtimeConnectivity after permission has been granted.

Using WNS to deliver notifications to a lock screen app

Some examples of a background task that can be activated by a WNS notification include the following:

  • Call the notification badge API to increment a badge icon for an email app on the lock screen to indicate that a new email message has arrived.
  • Call the modification toast API to raise a notification for a VoIP app signaling an incoming phone call for the user.

There are four types of push notifications:

  • Tile update
  • Badge update
  • Toast notification
  • Raw notification

All Metro style apps can use the first three push notifications when in the foreground. Only lock screen apps can receive raw push notifications from WNS.

Channels expire after 30 days, so there are best practices:

  • Register to get a new push notification channel every time your app starts, and send it to your server to replace the channel previously tied to the user.
  • For a local computer that is always powered, run a background task to renew the channel every once in a while before the channel expires. This is known as a maintenance timer.

The app must also register the background task to be activated when a push notification is received.

// Register the apps background task with the trigger for push notification task. // private void RegisterBackgroundTask() { BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder(); PushNotificationTrigger trigger = new PushNotificationTrigger(); taskBuilder.SetTrigger(trigger); // Background tasks must live in separate DLL, and be included in the package manifest // Also, make sure that your main application project includes a reference to this DLL taskBuilder.TaskEntryPoint = SAMPLE_TASK_ENTRY_POINT; taskBuilder.Name = SAMPLE_TASK_NAME; BackgroundTaskRegistration task = taskBuilder.Register(); task.Completed += BackgroundTaskCompleted; }

The following sample shows how to handle a raw push notification when in the background.

public sealed class SampleBackgroundTask : IBackgroundTask { public void Run(IBackgroundTaskInstance taskInstance) { // Get the background task details ApplicationDataContainer settings = ApplicationData.Current.LocalSettings; string taskName = taskInstance.Task.Name; Debug.WriteLine("Background " + taskName + " starting..."); // Store the content received from the raw push notification so it can be retrieved from the UI. RawNotification notification = (RawNotification)taskInstance.TriggerDetails; settings.Values[taskName] = notification.Content; Debug.WriteLine("Background " + taskName + " completed!"); } }

The maximum amount of data that can be included in the raw notification payload is 5KB.

Using a network trigger to deliver notifications to a lock screen app

The network trigger feature supports two network trigger types:

  • The pushnotification network trigger provides the capability for a Metro style app to process incoming network packets on a connected TCP socket even if the app is suspended. The connected TCP socket is sometimes referred to as the transport object or control channel. For the notification to reach the client app, this control channel must exist between the remote endpoint and the client. This control channel must be created by the client app in order for incoming network packets on this channel to trigger a background task. You can think of a control channel as a persistent TCP transport connection that is maintained by Windows and is maintained even when your application is in the background.

    Note The pushnotification trigger type is not related at all to push notifications and WNS.

  • The keep-alive network trigger provides a capability for the app to be suspended and send a keep-alive packet to the remote endpoint. This is important to help maintain the transport connection so the remote endpoint server does not close the connection. There is also a variant where a server-initiated keep-alive can also keep the control channel alive.

A lock screen app that uses the network trigger feature must register for the pushnotification trigger and should register for the keep-alive trigger. Together this ensures connectivity between the client and remote endpoint when the app is suspended.

The network trigger feature supports two possible resource types for a pushnotification or keep-alive network trigger:

  • Hardware slot
  • Software slot

This notion of slot is integral to the network trigger and is not required for WNS.

One of the options to specify while registering for the network trigger feature is the hardware or software slot resource type. This resource type capability provides a way for your app to be triggered by an incoming notification even if the device is in low power mode. By default, a software slot is selected if the developer does not specify an option. A software slot allows your app to be triggered when the system is not in connected standby. This is the default on most computers.

On the other hand, a hardware slot allows your app to be triggered at all times including when the system is in connected standby. Only systems with network devices that support connected standby will have a hardware slot. Note that the app cannot be triggered through a software or hardware slot when the system is in Sleep or Hibernate mode, or is shut down.

An app can create and use a maximum of 5 network triggers. There is also an additional system limitation on number of network triggers that specify hardware slots. The first 3 lock screen apps that register for a hardware slot for a network trigger can use a maximum of 3 hardware slots per app. Any other lock screen apps beyond the first three apps registered for hardware slots are limited to only software slots for their network triggers.

Register a background task to activate from a network trigger

The control channel trigger must be registered from a non-foreground app context, specifically a non-UI thread of the app. Note that creating a control channel in the UI thread will negatively impact the client app so it should be avoided.

Creating your control channel trigger

  1. Create a control channel.
  2. Open the transport connection.
  3. Associate the transport connection with the control channel.
  4. Connect the socket to the endpoint server. For some transports, this may be a connect operation. For some transports, this may be a send operation.
  5. Establish a transport connection to your remote endpoint server. After a successful connection to the server, finally synchronize the transport created by your app with lower layers of the operating system by using a specific API as shown in the following code snippet. This API allows the hardware or software slot to be registered with all the underlying layers of the stack that will handle an incoming data packet, including the network device driver.

private bool RegisterWithRTCBroker(StreamSocket sock) { ControlChannelTriggerStatus status; // // Step 1: Create the control channel object. // This.channel = new ControlChannelTrigger( "channelOne", // Channel ID to identify a control channel. 15, // Server-side keep-alive in minutes. ControlChannelTriggerResourceType.RequestHardwareSlot); // Request a hardware slot. // // Create a control channel trigger. // BackgroundTaskBuilder controlChannelBuilder = new BackgroundTaskBuilder(); controlChannelBuilder.Name = “ReceivePacketTaskChannelOne”; controlChannelBuilder.TaskEntryPoint = controlChannelBuilderActivationClassName; controlChannelBuilder.SetTrigger(channel.PushNotificationTrigger); controlChannelBuilder.Register(); // // Step 2: Open a socket connection (not shown here). // // // Step 3: Tie the transport object to the notification channel object. // channel.UsingTransport(sock); // Step 4: Connect the socket (not shown here). // // Step 5: Synchronize with lower layer to register the transport. // status = channel.WaitForPushEnabled(); }

The WaitForPushEnabled method is not related at all to push notifications and WNS.

It is important to note that a control channel trigger object will not accept a loopback connection. Hence, the transport connection must be established to another machine.

When a transport connection closes gracefully or due to abortive disconnect, it will result in the cleanup of hardware and software slots. When this happens there will be no further incoming notifications on this channel. The control channel trigger object itself can be reused for a new transport connection.

The second aspect of a network trigger–based lock screen app is to maintain the control channel through transient intermediate network devices and the destination server. This is done by sending periodic keep-alive messages on the persistent transport.

The control channel allows incoming messages to be delivered to apps. In order for this control channel path to be preserved between a client and the remote endpoint server, a keep-alive message must be sent at periodic intervals to the remote server. The keep-alive can be initiated from the server or the client. There are two variables in this path, the network keep-alive interval and the server keep-alive interval. The network keep-alive interval is the time for which intermediate network devices (such as NATs and proxy devices) will preserve the connection state when there is no traffic on the connection. The keep-alive helps ensure that traffic happens to prevent the socket from being closed.

Similarly, the server keep-alive interval is the frequency with which the server endpoint needs to hear from connected clients to consider that the client is still connected.

The registration for the keep-alive trigger can be done as part of the control channel registration.

Maintaining your control channel

// // Create control channel task (shown in previous snippet). // // Create keep-alive task. BackgroundTaskBuilder keepAliveBuilder = new BackgroundTaskBuilder(); keepAliveBuilder.Name = “KeepAliveTaskChannelOne”; keepAliveBuilder.TaskEntryPoint = KeepAliveTaskActivationClassName; keepAliveBuilder.SetTrigger(channel.KeepAliveTrigger); keepAliveBuilder.Register(); // // Step 2: Open a socket connection (not shown here). //

Windows will determine the optimal network keep-alive interval based on heuristic measurements for a given network. However, the server keep-alive interval must be provided by the app while registering the control channel trigger. The minimum server keep-alive time that can be provided by an app is 15 minutes. If a value lower than 15 minutes is provided, the system will assume a default value of 15 minutes.

The operating system accounts for both these values and chooses an optimum rate at which to send keep-alives for a given app on a given network that will preserve the control channel connection between client and the remote endpoint.

Note that the network keep-alive interval can be much lower than the server keep-alive provided by the app, because the operating system determines the optimal network keep-alive interval and chooses the lower of the two values. This optimal value is used for the keep-alive interval by the operating system to coalesce app use of CPU and network in order to improve battery life.

The keep-alive can be initiated by the client or the server. If the keep-alive is initiated by the server, the incoming notification message on the control channel will trigger a control channel trigger background task. This works well as long as the control channel is open; if the network connection is lost the app would not be aware of this loss, because it will be waiting for the incoming packet. To avoid this, an app can use the keep-alive trigger as a fallback to check for connectivity and re-establish the control channel if necessary.

Note that the keep-alive specified here is the app-level keep-alive, and is different from the TCP keep-alive, which is not used in this keep-alive trigger.

If your app has too many network connection losses, it is possible that the keep-alive interval chosen for the app is too long. In order to enable an app to provide this feedback, the DecreaseNetworkKeepAliveInterval method is provided as part of the ControlChannelTrigger object.

When an app calls DecreaseNetworkKeepAliveInterval, the operating system will reduce the keep-alive interval for the network triggers created for the corresponding channel ID. It will cache this value in a per-network location for a month. The app should call DecreaseNetworkKeepAliveInterval only if it determines that there is frequent connection loss. If necessary, the app may invoke the DecreaseNetworkKeepAliveInterval method more than once to request that Windows further lowers the keep-alive interval. However, Windows enforces a minimal value for the interval. If even after invoking DecreaseNetworkKeepAliveInterval the app continues to see connection losses on a given network, it may choose to not provide real-time connectivity options to its user. Since apps are sandboxed in terms of CPU and network I/O, frequently invoking this function will affect app performance.

Some apps may prefer to know the current keep-alive interval that is used by Windows. For such apps, the CurrentKeepAliveIntervalInMinutes property can be used to retrieve this information.

The CurrentKeepAliveIntervalInMinutes property returns the keep-alive interval in minutes. One example of an app using this value is for server-side keep-alive. The client app can use a value lower than the current keep-alive interval to set its server-side keep-alive interval. This way if the server does not respond within this interval, the client keep-alive timer will fire and the app can re-establish its control channel.

Writing your background task

The next step in making the app always reachable is to provide the app code that executes on a trigger. For example, in the case of VoIP, an incoming packet needs to execute app code to establish the VoIP call and potentially raise a notification to the user. This processing is done in the background task.

public sealed class controlChannelBuilderActivationClassName : Windows.AppModel.Background.IBackgroundTask{ public void Run(Windows.AppModel.Background.IBackgroundTaskInstance taskInstance) { IControlChannelTriggerEventDetails channelEventArgs = (IControlChannelTriggerEventDetails)taskInstance.TriggerDetails; ControlChannelTrigger channel = channelEventArgs.ControlChannelTrigger; string channelId = channel.ControlChannelTriggerId; string messageReceived = "Network packet received"; //InvokeSimpleToast(messageReceived); InvokeRingingToast(messageReceived); Channel.FlushTransport(); }}

The lifetime of the background task is controlled by the Run method. If an app exits the Run method, the app is suspended.

When an app background task is triggered, the operating system ensures that appropriate synchronization delivers the data on the transport connection to the app. Similarly, at the end of the background task an app must call the FlushTransport method to ensure that any pending data is sent before the app is suspended.

Remarks

There are several types of keep-alive intervals that may relate to network apps. At the lowest level, an app can set a TCP keep-alive option to send TCP keep-alive packets between a client app and a server to maintain an established TCP connection that is not being used. The KeepAlive property on the StreamSocketControl class allows an app to enable or disable this TCP keep-alive option on a StreamSocket. The default behavior for a StreamSocket is that TCP keep-alive is disabled. The MessageWebSocket, StreamSocketListener, andStreamWebSocket classes do not have an option to enable TCP keep-alive and this option is disabled by default. Similarly, the HttpClient class and the IXMLHTTPRequest2 object do not have an option to enable TCP keep-alive and this option is disabled by default.

In the context of the ControlChannelTrigger class, there are two other keep-alive intervals that have an impact.

  • Server keep-alive interval - This refers to a keep-alive interval in minutes that the network app registers with the system on how often to be woken up when the app has been suspended. The system will wake up the app based on the value set for this keep-alive interval. This value is represented by the ServerKeepAliveIntervalInMinutes property on a ControlChannelTrigger class and is set by the constructors to initialize a new ControlChannelTrigger instance. This value is considered a server keep-alive interval since a network app might normally set this based on known behavior of the server to which the app has established a TCP connection. For example, if it is known that a Web server will disconnect and drop TCP connections if there is no data sent by the app for 30 minutes, the network app could set this server keep-alive interval to say 25 minutes.
  • Network keep-alive interval - This refers to an internal keep-alive timer maintained by low-level network components in the TCP stack based on current network conditions. This value represents the value needed by network intermediaries to keep the TCP connection intact. These network intermediaries represent hardware and devices such as network proxies and network address translators. A network app cannot set this value, since this value is determined dynamically by low-level system components in the TCP stack . However, a network app can indicate to the system that the network keep-alive timer should be decreased if established TCP connections are regularly dropped by calling the DecreaseNetworkKeepAliveInterval method on a ControlChannelTrigger class.

Troubleshooting and debugging network connections

Note that the default policy in Windows 8 is to pick the unrestricted network over the metered network and the faster network over the slower network.

An app can register for network status change notifications (onNetworkStatusChanged) so it is notified when these network changes occur. If the connection the app was using is no longer available (indicated by an error), the app may need to do one of the following:

  • Retry the operation. If this fails, then wait for another NetworkStatusChanged notification.
  • Check the network cost and try to connect to a different network.

For instance, do not retry the operation if authentication fails, but retry the operation if a wireless network you were communicating with disappeared because another wireless network may be available. Many errors simply disappear when the operation is retried.

When you are testing your application and find errors that are not immediately obvious, you can enable ETW tracing to collect more details on the issue.

A built in diagnostic tool, CheckNetIsolation.exe, is provided to help developers test, diagnose and troubleshoot an app that requires network capabilities.

It has two main options:

LoopbackExempt

View a list of installed apps that are exempt from IP loopback restrictions and allowed access to loopback addresses. This option also allows adding access to IP loopback addresses for a specific app when testing.

Debug

Determines the enabled capabilities that are used by an app and any enabled capabilities that are unused. Any enabled capabilities that are not used make the app less secure. This option can also provides information on network traffic that was dropped,

Some CheckNetIsolation.exe options require the app name or the app ID be provided. Once an app is deployed on a target computer, the app name can be found under the c:\Program Files\Applications folder. This is the name used to start the app. This is the package family name displayed when using Microsoft Visual Studio 11 Beta and represents the App Container. The app ID can be found in the registry under the following key:

HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer

Enable loopback for network access

Network communications using an IP loopback address cannot be used for interprocess communication (between two different apps) since this is restricted by network isolation. Network communication using an IP loopback address is allowed within an app within the same process for communication purposes.

A developer may want to use loopback for testing or debugging purposes, even though that capability will not be available for customers. For example, an app may want to download data from a web service. For development purposes, the developer wants to test the app on a single computer that is configured with the web service locally on 127.0.0.1.

To enable access to loopback addresses, a developer must configure network isolation to exempt the app from loopback restrictions. For packets to be received by a network service, the listener on a TCP or UDP port also needs to be allowed by firewall rules.

Apps developed in Visual Studio will automatically be registered as being exempt from the loopback restrictions.

Debug network isolation issues

The debug option is used to generate a report of network capabilities that are used by an app.

The debug option provides a way to identify if an app is using all the capabilities that are declared in the app manifest. When the debug option is used, the system is instructed to track which of the declared capabilities the app is using and which declared capabilities are not used.

A detailed traffic report also lists the source and destination IP address used for network access.

Więcej szczegółów na How to enable loopback and troubleshoot network isolation.

Brak komentarzy: