Nozioni di base sulle reti

Operazioni da eseguire per qualsiasi app abilitata per la rete.

Funzionalità

Per poter usare funzionalità di rete, devi aggiungere funzionalità appropriate al manifesto dell'app. Se nel manifesto dell'app non è specificata alcuna funzionalità di rete, l'app non avrà funzionalità di rete e qualsiasi tentativo di connettersi alla rete avrà esito negativo.

Le funzionalità di rete più usate sono le seguenti.

Funzionalità Descrizione
internetClient Fornisce l'accesso in uscita a Internet e alle reti in luoghi pubblici, come gli aeroporti e i bar. Per la maggior parte delle app che richiedono l'accesso a Internet dovrebbe essere usata questa funzionalità.
internetClientServer Fornisce all'app l'accesso alla rete in ingresso e in uscita da Internet e reti in luoghi pubblici come aeroporti e bar.
privateNetworkClientServer Fornisce l'accesso in entrata e in uscita dell'app in luoghi attendibili, ad esempio a casa o in azienda.

Ci sono anche altre funzionalità che potrebbero essere necessarie in altre circostanze per la tua app.

Funzionalità Descrizione
enterpriseAuthentication Consente a un'app di connettersi alle risorse di rete che richiedono credenziali di dominio. Per esempio, un'app che recupera dati da server SharePoint in una Intranet privata. Grazie a questa funzionalità puoi usare le tue credenziali per accedere alle risorse di rete in una rete che richiede le credenziali. Questa funzionalità dell'app ti rappresenta in rete. Questa funzionalità non è obbligatoria per consentire all'app l'accesso a Internet tramite proxy di autenticazione.

Per altre informazioni, vedere la documentazione per l'Azienda dello scenario di funzionalità in Funzionalità limitate.
proximity Richiesta per la comunicazione NFC con dispositivi in prossimità del computer. La prossimità near-field potrebbe essere usata per l'invio o per la connessione con un'applicazione su un dispositivo in prossimità.

Questa funzionalità consente a un'app di accedere alla rete in modo da connettersi a un dispositivo in prossimità e, con il consenso dell'utente, di inviare o accettare un invito.
sharedUserCertificates Questa funzionalità consente a un'app di accedere a certificati software e hardware, ad esempio a certificati smart card. Quando si richiama questa funzionalità durante il runtime, l'utente deve intraprendere un'azione, ad esempio inserire la scheda o selezionare un certificato.

Grazie a questa funzionalità, i tuoi certificati software e hardware o una smart card vengono usati per l'identificazione nell'app. Questa funzionalità può essere usata dal tuo datore di lavoro, dalla banca o dagli uffici pubblici per l'identificazione.

Come comunicare quando l'app non è in primo piano

L'argomento Supportare l'app con attività in background contiene informazioni generali sull'uso di attività in background per lavorare quando l'app non è in primo piano. Più esattamente, il codice deve eseguire operazioni particolari per ricevere una notifica quando non è l'app in primo piano e tramite la rete arrivano dati destinati all'app. A questo scopo in Windows 8 si usano i trigger canale di controllo che sono ancora supportati in Windows 10. Per informazioni complete sull'uso dei trigger canale di controllo, vedi qui. Una nuova tecnologia disponibile in Windows 10 offre funzionalità migliori con un sovraccarico minore per alcuni scenari, come i socket di flusso abilitati per il push. Tale tecnologia è costituita dal broker del socket e dai trigger di attività socket.

Se la tua app usa DatagramSocket, StreamSocket o StreamSocketListener, può trasferire la proprietà di un socket aperto a un gestore del socket fornito dal sistema e quindi lasciare il primo piano o persino essere terminata. Quando viene effettuata una connessione tramite il socket trasferito o arriva traffico su tale socket, vengono attivati l'app o l'attività in background designata. Se l'app non è in esecuzione, viene avviata. Il gestore del socket notifica quindi all'app l'arrivo di nuovo traffico tramite un elemento SocketActivityTrigger. L'app recupera il socket dal broker del socket ed elabora il traffico presente sul socket. Questo significa che l'app consuma meno risorse di sistema quando non elabora attivamente il traffico di rete.

Il gestore del socket può essere usato in sostituzione dei trigger canale di controllo laddove possibile perché offre la stessa funzionalità, ma implica meno restrizioni e meno consumo di memoria. Può essere usato da app, purché non siano app schermata di blocco, in modo analogo su telefoni e su altri dispositivi. Per poter essere attivate dal gestore del socket, le app non devono essere in esecuzione all'arrivo del traffico. Il gestore del socket supporta inoltre l'ascolto su socket TCP, che non è supportato dai trigger canale di controllo.

Scelta di un trigger di rete

In alcuni scenari si può usare indifferentemente l'uno o l'altro tipo di trigger. Quando scegli il tipo di trigger da usare nella tua app, tieni in considerazione i consigli seguenti.

Per dettagli ed esempi su come usare il gestore del socket, vedi Comunicazioni di rete in background.

Connessioni sicure

SSL (Secure Sockets Layer) e il più recente TLS (Transport Layer Security) sono protocolli di crittografia progettati per fornire servizi di autenticazione e crittografia per le comunicazioni di rete. Questi protocolli impediscono l'intercettazione e la manomissione durante l'invio e la ricezione di dati di rete. Per gli scambi dei protocolli viene usato un modello client-server. Questi protocolli usano inoltre certificati digitali e autorità di certificazione per verificare l'identità del server.

Creazione di connessioni socket sicure

Puoi configurare un oggetto StreamSocket in modo da usare SSL/TLS per le comunicazioni tra il client e il server. Il supporto di SSL/TLS è disponibile solo quando l'oggetto StreamSocket viene usato come client nella negoziazione SSL/TLS. Non puoi usare SSL/TLS con l'oggetto StreamSocket creato da una classe StreamSocketListener quando vengono ricevute comunicazioni in ingresso, perché la negoziazione SSL/TLS come server non è implementata dalla classe StreamSocket.

Per proteggere una connessione StreamSocket usando SSL/TLS, puoi scegliere tra due modalità:

  • ConnectAsync: È possibile impostare la connessione iniziale a un servizio di rete e negoziare immediatamente l'uso di SSL/TLS per tutte le comunicazioni.
  • UpgradeToSslAsync:È possibile stabilire inizialmente la connessione a un servizio di rete senza crittografia. Dopo che l'app ha inviato o ricevuto alcuni dati, puoi aggiornare la connessione in modo da usare SSL/TLS per tutte le future comunicazioni.

SocketProtectionLevel specifica il livello di protezione socket richiesto tramite cui l'app vuole stabilire o aggiornare la connessione. Tuttavia, il livello di protezione finale della connessione stabilita viene determinato in un processo di negoziazione tra entrambi gli endpoint della connessione. Il risultato può essere un livello di protezione inferiore rispetto a quello specificato, se l'altro endpoint richiede un livello più basso.

Al termine dell'operazione asincrona, è possibile recuperare il livello di protezione richiesto usato nella chiamata ConnectAsync o UpgradeToSslAsync tramite la proprietà StreamSocketinformation.ProtectionLevel. Il livello recuperato non riflette tuttavia il livello di protezione effettivo usato dalla connessione.

Nota

Il codice non dovrebbe dipendere in modo implicito da un particolare livello di protezione oppure dal presupposto che venga usato per impostazione predefinita un determinato livello di sicurezza. Il panorama della sicurezza è soggetto a cambiamenti costanti e i protocolli e i livelli di protezione predefiniti verranno modificati nel corso del tempo per evitare l'uso dei protocolli con vulnerabilità note. Le impostazioni predefinite possono variare in base alla configurazione dei singoli computer oppure al software installato o alle patch applicate. Se l'app dipende dall'uso di un livello di sicurezza specifico, specificare in modo esplicito quel livello e quindi verificare che sia effettivamente in uso per la connessione stabilita.

Usare ConnectAsync

È possibile usare ConnectAsync per stabilire la connessione iniziale a un servizio di rete e quindi negoziare immediatamente l'uso di SSL/TLS per tutte le comunicazioni. Esistono due metodi ConnectAsync che supportano il passaggio di un parametro protectionLevel:

Se il parametro protectionLevel è impostato su Windows.Networking.Sockets.SocketProtectionLevel.Ssl durante la chiamata di uno dei metodi ConnectAsync indicati sopra, StreamSocket deve usare SSL/TLS per la crittografia. Questo valore richiede la crittografia e non consente mai di usare NULL.

La sequenza da seguire è la stessa per entrambi i metodi ConnectAsync.

L'esempio seguente crea un oggetto StreamSocket e quindi tenta di stabilire una connessione al servizio di rete e di negoziare immediatamente l'uso di SSL/TLS. Se la negoziazione ha esito positivo, tutte le comunicazioni di rete che usano StreamSocket tra il client e il server di rete verranno crittografate.

using Windows.Networking;
using Windows.Networking.Sockets;

    // Define some variables and set values
    StreamSocket clientSocket = new StreamSocket();
     
    HostName serverHost = new HostName("www.contoso.com");
    string serverServiceName = "https";
    
    // For simplicity, the sample omits implementation of the
    // NotifyUser method used to display status and error messages 
    
    // Try to connect to contoso using HTTPS (port 443)
    try {

        // Call ConnectAsync method with SSL
        await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.Ssl);

        NotifyUser("Connected");
    }
    catch (Exception exception) {
        // If this is an unknown status it means that the error is fatal and retry will likely fail.
        if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
            throw;
        }
        
        NotifyUser("Connect failed with error: " + exception.Message);
        // Could retry the connection, but for this simple example
        // just close the socket.
        
        clientSocket.Dispose();
        clientSocket = null; 
    }
           
    // Add code to send and receive data using the clientSocket
    // and then close the clientSocket
#include <winrt/Windows.Networking.Sockets.h>

using namespace winrt;
...
    // Define some variables, and set values.
    Windows::Networking::Sockets::StreamSocket clientSocket;

    Windows::Networking::HostName serverHost{ L"www.contoso.com" };
    winrt::hstring serverServiceName{ L"https" };

    // For simplicity, the sample omits implementation of the
    // NotifyUser method used to display status and error messages.

    // Try to connect to the server using HTTPS and SSL (port 443).
    try
    {
        co_await clientSocket.ConnectAsync(serverHost, serverServiceName, Windows::Networking::Sockets::SocketProtectionLevel::Tls12);
        NotifyUser(L"Connected");
    }
    catch (winrt::hresult_error const& exception)
    {
        NotifyUser(L"Connect failed with error: " + exception.message());
        clientSocket = nullptr;
    }
    // Add code to send and receive data using the clientSocket,
    // then set the clientSocket to nullptr when done to close it.
using Windows::Networking;
using Windows::Networking::Sockets;

    // Define some variables and set values
    StreamSocket^ clientSocket = new ref StreamSocket();
 
    HostName^ serverHost = new ref HostName("www.contoso.com");
    String serverServiceName = "https";

    // For simplicity, the sample omits implementation of the
    // NotifyUser method used to display status and error messages 

    // Try to connect to the server using HTTPS and SSL (port 443)
    task<void>(clientSocket->ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel::SSL)).then([this] (task<void> previousTask) {
        try
        {
            // Try getting all exceptions from the continuation chain above this point.
            previousTask.Get();
            NotifyUser("Connected");
        }
        catch (Exception^ exception)
        {
            NotifyUser("Connect failed with error: " + exception->Message);
            
            clientSocket.Close();
            clientSocket = null;
        }
    });
    // Add code to send and receive data using the clientSocket
    // Then close the clientSocket when done

Usare UpgradeToSslAsync

Quando il tuo codice usa UpgradeToSslAsync, stabilisce inizialmente una connessione a un servizio di rete senza crittografia. Dopo che l'app ha inviato o ricevuto alcuni dati, aggiorna la connessione in modo da usare SSL/TLS per tutte le future comunicazioni.

Il metodo UpgradeToSslAsync accetta due parametri. Il parametro protectionLevel indica il livello di protezione desiderato. Il parametro validationHostName indica il nome host della destinazione di rete remota usato per la convalida durante l'aggiornamento a SSL. In genere, il parametro validationHostName contiene il nome host usato dall'app per stabilire inizialmente la connessione. Se il parametro protectionLevel è impostato su Windows.System.Socket.SocketProtectionLevel.Ssl durante la chiamata di UpgradeToSslAsync, StreamSocket deve usare SSL/TLS per la crittografia di ulteriori comunicazioni sul socket. Questo valore richiede la crittografia e non consente mai di usare NULL.

La sequenza da seguire con il metodo UpgradeToSslAsync è la seguente:

L'esempio seguente crea un oggetto StreamSocket, tenta di stabilire una connessione al servizio di rete, invia alcuni dati iniziali e quindi negozia l'uso di SSL/TLS. Se la negoziazione ha esito positivo, tutte le comunicazioni di rete che usano StreamSocket tra il client e il server di rete verranno crittografate.

using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

    // Define some variables and set values
    StreamSocket clientSocket = new StreamSocket();
 
    HostName serverHost = new HostName("www.contoso.com");
    string serverServiceName = "http";

    // For simplicity, the sample omits implementation of the
    // NotifyUser method used to display status and error messages 

    // Try to connect to contoso using HTTP (port 80)
    try {
        // Call ConnectAsync method with a plain socket
        await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.PlainSocket);

        NotifyUser("Connected");

    }
    catch (Exception exception) {
        // If this is an unknown status it means that the error is fatal and retry will likely fail.
        if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
            throw;
        }

        NotifyUser("Connect failed with error: " + exception.Message, NotifyType.ErrorMessage);
        // Could retry the connection, but for this simple example
        // just close the socket.

        clientSocket.Dispose();
        clientSocket = null; 
        return;
    }

    // Now try to send some data
    DataWriter writer = new DataWriter(clientSocket.OutputStream);
    string hello = "Hello, World! ☺ ";
    Int32 len = (int) writer.MeasureString(hello); // Gets the UTF-8 string length.
    writer.WriteInt32(len);
    writer.WriteString(hello);
    NotifyUser("Client: sending hello");

    try {
        // Call StoreAsync method to store the hello message
        await writer.StoreAsync();

        NotifyUser("Client: sent data");

        writer.DetachStream(); // Detach stream, if not, DataWriter destructor will close it.
    }
    catch (Exception exception) {
        NotifyUser("Store failed with error: " + exception.Message);
        // Could retry the store, but for this simple example
            // just close the socket.

            clientSocket.Dispose();
            clientSocket = null; 
            return;
    }

    // Now upgrade the client to use SSL
    try {
        // Try to upgrade to SSL
        await clientSocket.UpgradeToSslAsync(SocketProtectionLevel.Ssl, serverHost);

        NotifyUser("Client: upgrade to SSL completed");
           
        // Add code to send and receive data 
        // The close clientSocket when done
    }
    catch (Exception exception) {
        // If this is an unknown status it means that the error is fatal and retry will likely fail.
        if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
            throw;
        }

        NotifyUser("Upgrade to SSL failed with error: " + exception.Message);

        clientSocket.Dispose();
        clientSocket = null; 
        return;
    }
#include <winrt/Windows.Networking.Sockets.h>
#include <winrt/Windows.Storage.Streams.h>

using namespace winrt;
using namespace Windows::Storage::Streams;
...
    // Define some variables, and set values.
    Windows::Networking::Sockets::StreamSocket clientSocket;

    Windows::Networking::HostName serverHost{ L"www.contoso.com" };
    winrt::hstring serverServiceName{ L"https" };

    // For simplicity, the sample omits implementation of the
    // NotifyUser method used to display status and error messages. 

    // Try to connect to the server using HTTP (port 80).
    try
    {
        co_await clientSocket.ConnectAsync(serverHost, serverServiceName, Windows::Networking::Sockets::SocketProtectionLevel::PlainSocket);
        NotifyUser(L"Connected");
    }
    catch (winrt::hresult_error const& exception)
    {
        NotifyUser(L"Connect failed with error: " + exception.message());
        clientSocket = nullptr;
    }

    // Now, try to send some data.
    DataWriter writer{ clientSocket.OutputStream() };
    winrt::hstring hello{ L"Hello, World! ☺ " };
    uint32_t len{ writer.MeasureString(hello) }; // Gets the size of the string, in bytes.
    writer.WriteInt32(len);
    writer.WriteString(hello);
    NotifyUser(L"Client: sending hello");

    try
    {
        co_await writer.StoreAsync();
        NotifyUser(L"Client: sent hello");

        writer.DetachStream(); // Detach the stream when you want to continue using it; otherwise, the DataWriter destructor closes it.
    }
    catch (winrt::hresult_error const& exception)
    {
        NotifyUser(L"Store failed with error: " + exception.message());
        // We could retry the store operation. But, for this simple example, just close the socket by setting it to nullptr.
        clientSocket = nullptr;
        co_return;
    }

    // Now, upgrade the client to use SSL.
    try
    {
        co_await clientSocket.UpgradeToSslAsync(Windows::Networking::Sockets::SocketProtectionLevel::Tls12, serverHost);
        NotifyUser(L"Client: upgrade to SSL completed");

        // Add code to send and receive data using the clientSocket,
        // then set the clientSocket to nullptr when done to close it.
    }
    catch (winrt::hresult_error const& exception)
    {
        // If this is an unknown status, then the error is fatal and retry will likely fail.
        Windows::Networking::Sockets::SocketErrorStatus socketErrorStatus{ Windows::Networking::Sockets::SocketError::GetStatus(exception.to_abi()) };
        if (socketErrorStatus == Windows::Networking::Sockets::SocketErrorStatus::Unknown)
        {
            throw;
        }

        NotifyUser(L"Upgrade to SSL failed with error: " + exception.message());
        // We could retry the store operation. But for this simple example, just close the socket by setting it to nullptr.
        clientSocket = nullptr;
        co_return;
    }
using Windows::Networking;
using Windows::Networking::Sockets;
using Windows::Storage::Streams;

    // Define some variables and set values
    StreamSocket^ clientSocket = new ref StreamSocket();
 
    Hostname^ serverHost = new ref HostName("www.contoso.com");
    String serverServiceName = "http";

    // For simplicity, the sample omits implementation of the
    // NotifyUser method used to display status and error messages 

    // Try to connect to contoso using HTTP (port 80)
    task<void>(clientSocket->ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel::PlainSocket)).then([this] (task<void> previousTask) {
        try
        {
            // Try getting all exceptions from the continuation chain above this point.
            previousTask.Get();
            NotifyUser("Connected");
        }
        catch (Exception^ exception)
        {
            NotifyUser("Connect failed with error: " + exception->Message);
 
            clientSocket->Close();
            clientSocket = null;
        }
    });
       
    // Now try to send some data
    DataWriter^ writer = new ref DataWriter(clientSocket.OutputStream);
    String hello = "Hello, World! ☺ ";
    Int32 len = (int) writer->MeasureString(hello); // Gets the UTF-8 string length.
    writer->writeInt32(len);
    writer->writeString(hello);
    NotifyUser("Client: sending hello");

    task<void>(writer->StoreAsync()).then([this] (task<void> previousTask) {
        try {
            // Try getting all exceptions from the continuation chain above this point.
            previousTask.Get();

            NotifyUser("Client: sent hello");

            writer->DetachStream(); // Detach stream, if not, DataWriter destructor will close it.
       }
       catch (Exception^ exception) {
               NotifyUser("Store failed with error: " + exception->Message);
               // Could retry the store, but for this simple example
               // just close the socket.
 
               clientSocket->Close();
               clientSocket = null;
               return
       }
    });

    // Now upgrade the client to use SSL
    task<void>(clientSocket->UpgradeToSslAsync(clientSocket.SocketProtectionLevel.Ssl, serverHost)).then([this] (task<void> previousTask) {
        try {
            // Try getting all exceptions from the continuation chain above this point.
            previousTask.Get();

           NotifyUser("Client: upgrade to SSL completed");
           
           // Add code to send and receive data 
           // Then close clientSocket when done
        }
        catch (Exception^ exception) {
            // If this is an unknown status it means that the error is fatal and retry will likely fail.
            if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
                throw;
            }

            NotifyUser("Upgrade to SSL failed with error: " + exception.Message);

            clientSocket->Close();
            clientSocket = null; 
            return;
        }
    });

Creazione di connessioni WebSocket sicure

Come le connessioni socket tradizionali, anche le connessioni WebSocket possono essere crittografate con Transport Layer Security (TLS)/Secure Sockets Layer (SSL) quando usi le funzionalità StreamWebSocket e MessageWebSocket di Windows 8 per un'app UWP. Nella maggior parte dei casi è preferibile usare una connessione WebSocket sicura. In questo modo le probabilità di riuscita della connessione aumentano, perché molti proxy rifiutano connessioni WebSocket non crittografate.

Per esempi di come creare una connessione socket sicura a un servizio di rete o eseguire l'aggiornamento a questo tipo di connessione, vedi Come proteggere le connessioni WebSocket con TLS/SSL.

Oltre alla crittografia TLS/SSL, un server potrebbe richiedere un valore di intestazione Sec-WebSocket-Protocol per eseguire l'handshake iniziale. Questo valore, rappresentato dalle proprietà StreamWebSocketInformation.Protocol e MessageWebSocketInformation.Protocol, indica la versione del protocollo della connessione e consente al server di interpretare correttamente l'handshake di apertura e i dati scambiati in seguito. Usando queste informazioni di protocollo, la connessione può essere chiusa se in qualsiasi momento il server non è in grado di interpretare i dati in ingresso in modo sicuro.

Se la richiesta iniziale dal client non contiene questo valore o fornisce un valore non corrispondente a quello previsto dal server, il valore previsto viene inviato dal server al client in caso di errore di handshake WebSocket.

Autenticazione

Questa sezione spiega come fornire le credenziali di autenticazione per la connessione in rete.

Specifica di un certificato client con la classe StreamSocket

La classe Windows.Networking.Sockets.StreamSocket supporta l'uso di SSL/TLS per autenticare il server con cui comunica l'app. In casi specifici l'app deve eseguire l'autenticazione anche con il server che usa un certificato client TLS. In Windows 10 è possibile fornire un certificato client nell'oggetto StreamSocket.Control, che però deve essere impostato prima dell'inizio dell'handshake TLS. Se il server richiede il certificato client, Windows risponderà con il certificato fornito.

Ecco un frammento di codice che illustra come implementare questo comportamento:

var socket = new StreamSocket();
Windows.Security.Cryptography.Certificates.Certificate certificate = await GetClientCert();
socket.Control.ClientCertificate = certificate;
await socket.ConnectAsync(destination, SocketProtectionLevel.Tls12);

Passaggio delle credenziali di autenticazione a un servizio Web

Le API di rete che consentono alle app di interagire con servizi Web sicuri forniscono ognuna metodi specifici per inizializzare un client o impostare un'intestazione di richiesta con le credenziali di autenticazione per server e proxy. Ogni metodo viene impostato con un oggetto PasswordCredential che indica un nome utente, una password e la risorsa per cui vengono usate le credenziali. La tabella seguente riporta un mapping delle API:

WebSocket MessageWebSocketControl.ServerCredential
MessageWebSocketControl.ProxyCredential
StreamWebSocketControl.ServerCredential
StreamWebSocketControl.ProxyCredential
Trasferimento in background BackgroundDownloader.ServerCredential
BackgroundDownloader.ProxyCredential
BackgroundUploader.ServerCredential
BackgroundUploader.ProxyCredential
Diffusione SyndicationClient(PasswordCredential)
SyndicationClient.ServerCredential
SyndicationClient.ProxyCredential
AtomPub AtomPubClient(PasswordCredential)
AtomPubClient.ServerCredential
AtomPubClient.ProxyCredential

Gestione delle eccezioni di rete

Nella maggior parte delle aree di programmazione un'eccezione indica un problema o un errore causato da alcuni bug nel programma. Nella programmazione di rete le eccezioni possono inoltre essere causate dalla rete stessa e dalla natura delle comunicazioni di rete. Le comunicazioni di rete sono intrinsecamente inaffidabili e soggette a errori imprevisti. Per ognuno dei modi in cui l'app usa le funzionalità di rete devi mantenere alcune informazioni sullo stato. Il codice dell'app deve inoltre gestire le eccezioni di rete aggiornando le informazioni sullo stato e avviando la logica appropriata per ripristinare la comunicazione con l'app in caso di errori.

Quando le app di Windows universale generano un'eccezione, il gestore delle eccezioni può recuperare ulteriori dettagli sulla causa in modo da comprendere meglio l'errore e prendere le decisioni appropriate.

Ogni proiezione di linguaggio supporta un metodo per accedere a queste informazioni dettagliate. Un'eccezione viene proiettata come un valore HRESULT nelle app di Windows universale. Il file Winerror.h include un elenco molto lungo di possibili valori HRESULT che include gli errori di rete.

Le API di rete supportano diversi metodi per recuperare informazioni dettagliate sulla causa di un'eccezione.

  • Alcune API forniscono un metodo helper che converte il valore HRESULT dell'eccezione in un valore di enumerazione.
  • Altre API forniscono invece un metodo per recuperare il valore effettivo di HRESULT.