Conceptos básicos de redes

Las cosas que debe hacer para cualquier aplicación habilitada para la red.

Capacidades

Para usar las redes, debes agregar los elementos de funcionalidad adecuados al manifiesto de la aplicación. Si no se especifica ninguna funcionalidad de red en el manifiesto de la aplicación, la aplicación no tendrá ninguna funcionalidad de red y se producirá un error en cualquier intento de conexión a la red.

A continuación se muestran las funcionalidades de red más usadas.

Capacidad Descripción
internetClient Proporciona acceso saliente a Internet y redes en lugares públicos, como aeropuertos y cafeterías. La mayoría de las aplicaciones que requieren acceso a Internet deben usar esta funcionalidad.
internetClientServer Proporciona a la aplicación acceso de red entrante y saliente desde Internet y redes en lugares públicos como aeropuertos y cafeterías.
privateNetworkClientServer Proporciona a la aplicación acceso de red entrante y saliente en los lugares de confianza del usuario, como el hogar y el trabajo.

Hay otras funcionalidades que podrían ser necesarias para la aplicación, en determinadas circunstancias.

Capacidad Descripción
enterpriseAuthentication Permite a una aplicación conectarse a recursos de red que requieren credenciales de dominio. Por ejemplo, una aplicación que recupera datos de servidores de SharePoint en una intranet privada. Con esta funcionalidad, las credenciales se pueden usar para acceder a los recursos de red de una red que requiera credenciales. Una aplicación con esta funcionalidad puede suplantar a usted en la red. No necesita esta funcionalidad para permitir que la aplicación acceda a Internet a través de un proxy de autenticación.

Para obtener más información, consulte la documentación del escenario de funcionalidad Enterprise en Funcionalidades restringidas.
proximidad Es necesaria para la comunicación de datos en proximidad con dispositivos que se encuentran cerca del equipo. La comunicación de datos en proximidad puede usarse para realizar envíos o para conectar con una aplicación de un dispositivo cercano.

Esta funcionalidad permite a una aplicación acceder a la red para conectarse a un dispositivo cerca, con el consentimiento del usuario para enviar una invitación o aceptar una invitación.
sharedUserCertificates Esta funcionalidad permite a una aplicación acceder a certificados de software y hardware, como certificados de tarjeta inteligente. Cuando se invoca esta funcionalidad en tiempo de ejecución, el usuario debe tomar medidas, como insertar una tarjeta o seleccionar un certificado.

Con esta funcionalidad, los certificados de software y hardware o una tarjeta inteligente se usan para la identificación en la aplicación. Esta funcionalidad puede ser utilizada por su empleador, banco o servicios gubernamentales para su identificación.

Comunicación cuando la aplicación no está en primer plano

Las tareas en segundo plano proporcionan información general sobre cómo realizar el trabajo cuando la aplicación no está en primer plano. Más concretamente, tu código debe realizar unos pasos especiales para recibir notificaciones cuando no es la aplicación en primer plano actual y llegan datos a través de la red para esta. Los desencadenadores de canal de control se admiten en Windows para este propósito. Para obtener más información, consulte ControlChannelTrigger. Existe una tecnología más reciente que ofrece una mejor funcionalidad con una menor sobrecarga en algunos escenarios, como los sockets de flujo habilitados para push: el bróker de sockets y los desencadenantes de actividad de sockets.

Si la aplicación usa DatagramSocket, StreamSocket o StreamSocketListener, la aplicación puede transferir la propiedad de un socket abierto a un agente de socket proporcionado por el sistema y, a continuación, dejar el primer plano o incluso finalizar. Cuando se realiza una conexión en el socket transferido, o el tráfico llega a ese socket, la aplicación o su tarea en segundo plano designada se activan. Si la aplicación no se está ejecutando, se inicia. A continuación, el agente de socket notifica a la aplicación mediante socketActivityTrigger que ha llegado el tráfico nuevo. Es entonces cuando la aplicación recupera el socket desde el agente de sockets y procesa el tráfico en el mismo socket. Esto significa que la aplicación consume mucho menos recursos del sistema cuando no está procesando activamente el tráfico de red.

El intermediario de sockets está diseñado para reemplazar los desencadenadores del canal de control cuando corresponda, ya que proporciona la misma funcionalidad pero con menos restricciones y un menor consumo de memoria. El agente de socket puede usarse en aplicaciones que no son aplicaciones con pantalla de bloqueo y se usa la misma manera en los teléfonos como en otros dispositivos. Las aplicaciones no necesitan estar en ejecución cuando llega tráfico para ser activadas por el intermediario de sockets. Además, el agente de socket admite la capacidad de escuchar en los sockets TCP, que no son compatibles con los desencadenadores de canal de control.

Elección de un desencadenador de red

Hay algunos escenarios en los que cualquier tipo de desencadenador sería adecuado. Al elegir qué tipo de desencadenador usar en la aplicación, tenga en cuenta los siguientes consejos.

Para más información y ejemplos de cómo usar el agente de sockets, consulte Comunicaciones de red en segundo plano.

Conexiones protegidas

Secure Sockets Layer (SSL) y el más reciente Seguridad de la capa de transporte (TLS) son protocolos criptográficos diseñados para proporcionar autenticación y cifrado para las comunicaciones de red. Estos protocolos están diseñados para evitar interceptaciones y alteraciones al enviar y recibir datos de red. Estos protocolos usan un modelo de cliente-servidor para los intercambios de protocolos. Estos protocolos también usan certificados digitales y entidades de certificación para comprobar que el servidor es quien dice ser.

Creación de conexiones seguras de socket

Se puede configurar un objeto StreamSocket para usar SSL/TLS para las comunicaciones entre el cliente y el servidor. Esta compatibilidad con SSL/TLS se limita al uso del objeto StreamSocket como cliente en la negociación SSL/TLS. No se puede usar SSL/TLS con streamSocket creado por streamSocketListener cuando se reciben las comunicaciones entrantes, ya que la clase StreamSocket no implementa la negociación SSL/TLS como servidor.

Hay dos maneras de proteger una conexión StreamSocket con SSL/TLS:

  • ConnectAsync : realice la conexión inicial a un servicio de red y negocie inmediatamente el uso de SSL/TLS para todas las comunicaciones.
  • UpgradeToSslAsync : conéctese inicialmente a un servicio de red sin cifrado. La aplicación puede enviar o recibir datos. A continuación, actualice la conexión para usar SSL/TLS para todas las comunicaciones adicionales.

SocketProtectionLevel especifica el nivel de protección de socket deseado con el que la aplicación quiere establecer o actualizar la conexión. Sin embargo, el nivel de protección final de la conexión establecida se determina en un proceso de negociación entre ambos puntos de conexión de la conexión. El resultado puede ser un nivel de protección inferior al especificado, si el otro punto de conexión solicita un nivel inferior.

Una vez completada correctamente la operación asincrónica, puede recuperar el nivel de protección solicitado usado en la llamada ConnectAsync o UpgradeToSslAsync a través de la propiedad StreamSocketInformation.ProtectionLevel . Sin embargo, esto no refleja el nivel de protección real que usa la conexión.

Note

El código no debe depender implícitamente del uso de un nivel de protección determinado o de la suposición de que se usa de forma predeterminada un nivel de seguridad determinado. El panorama de seguridad cambia constantemente, y los protocolos y los niveles de protección predeterminados cambian con el tiempo para evitar el uso de protocolos con puntos débiles conocidos. Los valores predeterminados pueden variar en función de la configuración de la máquina individual o en qué software está instalado y qué revisiones se han aplicado. Si la aplicación depende del uso de un nivel de seguridad determinado, debe especificar explícitamente ese nivel y, a continuación, comprobar que realmente está en uso en la conexión establecida.

Uso de ConnectAsync

ConnectAsync se puede usar para establecer la conexión inicial con un servicio de red y, a continuación, negociar inmediatamente para usar SSL/TLS para todas las comunicaciones. Hay dos métodos ConnectAsync que admiten pasar un parámetro protectionLevel :

Si el parámetro protectionLevel se establece en Windows. Networking.Sockets.SocketProtectionLevel.Ssl al llamar a cualquiera de los métodos ConnectAsync anteriores, se establecerá StreamSocket para usar SSL/TLS para el cifrado. Este valor requiere cifrado y nunca permite usar un cifrado NULL.

La secuencia normal que se va a usar con uno de estos métodos ConnectAsync es la misma.

  • Cree un StreamSocket.
  • Si se necesita una opción avanzada en el socket, use la propiedad StreamSocket.Control para obtener la instancia de StreamSocketControl asociada a un objeto StreamSocket . Establezca una propiedad en StreamSocketControl.
  • Llame a uno de los métodos ConnectAsync anteriores para iniciar una operación para conectarse a un destino remoto e negociar inmediatamente el uso de SSL/TLS.
  • El nivel de seguridad de SSL que realmente se negocia al usar ConnectAsync puede determinarse obteniendo la propiedad StreamSocketInformation.ProtectionLevel después de que la operación asincrónica se haya completado correctamente.

En el ejemplo siguiente se crea un StreamSocket y se intenta establecer una conexión con el servicio de red y negociar de inmediato el uso de SSL/TLS. Si la negociación se realiza correctamente, toda la comunicación de red mediante StreamSocket entre el cliente que el servidor de red se cifrará.

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 = ref new StreamSocket();
 
    HostName^ serverHost = ref 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 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

Uso de UpgradeToSslAsync

Cuando el código usa UpgradeToSslAsync, primero establece una conexión a un servicio de red sin cifrado. La aplicación puede enviar o recibir algunos datos y, a continuación, actualizar la conexión para usar SSL/TLS para todas las comunicaciones posteriores.

El método UpgradeToSslAsync toma dos parámetros. El parámetro protectionLevel indica el nivel de protección deseado. El parámetro validationHostName es el nombre de host del destino de red remota que se usa para la validación al actualizar a SSL. Normalmente , validationHostName sería el mismo nombre de host que la aplicación usó para establecer inicialmente la conexión. Si el parámetro protectionLevel se establece en Windows. System.Socket.SocketProtectionLevel.Ssl al llamar a UpgradeToSslAsync, StreamSocket debe usar SSL/TLS para el cifrado en comunicaciones adicionales a través del socket. Este valor requiere cifrado y nunca permite usar un cifrado NULL.

La secuencia normal que se va a usar con el método UpgradeToSslAsync es la siguiente:

En el ejemplo siguiente se crea un objeto StreamSocket, se intenta establecer una conexión con el servicio de red, se envían algunos datos iniciales y, a continuación, se negocia el uso de SSL/TLS. Si la negociación se realiza correctamente, se cifrará toda la comunicación de red mediante StreamSocket entre el cliente y el servidor de red.

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 = ref new StreamSocket();
 
    HostName^ serverHost = ref 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)
    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 = ref 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");

    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(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;
        }
    });

Creación de conexiones seguras de WebSocket

Al igual que las conexiones de socket tradicionales, las conexiones WebSocket también se pueden cifrar con la seguridad de la capa de transporte (TLS)/Capa de sockets seguros (SSL) al usar las características StreamWebSocket y MessageWebSocket para una aplicación de Windows. En la mayoría de los casos, querrá usar una conexión WebSocket segura. Esto aumentará las posibilidades de que la conexión se realice correctamente, ya que muchos servidores proxy rechazarán las conexiones WebSocket sin cifrar.

Para obtener ejemplos de cómo crear o actualizar a una conexión de socket seguro a un servicio de red, consulte Protección de conexiones de WebSocket con TLS/SSL.

Además del cifrado con TLS/SSL, es posible que un servidor necesite un valor de encabezado Sec-WebSocket-Protocol para completar el protocolo de enlace inicial. Este valor, representado por las propiedades StreamWebSocketInformation.Protocol y MessageWebSocketInformation.Protocol , indica la versión del protocolo de conexión y permite al servidor interpretar correctamente el protocolo de enlace de apertura y los datos que se intercambian posteriormente. Con esta información de protocolo, si en algún momento el servidor no puede interpretar los datos entrantes de forma segura, se puede cerrar la conexión.

Si la solicitud inicial del cliente no contiene este valor o proporciona un valor que no coincide con lo que espera el servidor, el valor esperado se envía desde el servidor al cliente en el error de protocolo de enlace WebSocket.

Autenticación

Cómo proporcionar credenciales de autenticación al conectarse a través de la red.

Proporcionar un certificado de cliente con la clase StreamSocket

La clase Windows.Networking.Sockets.StreamSocket permite usar SSL/TLS para autenticar el servidor con el que se comunica la aplicación. En determinados casos, la aplicación también debe autenticarse en el servidor mediante un certificado de cliente TLS. En Windows 10, puede proporcionar un certificado de cliente en el objeto StreamSocket.Control (debe establecerse antes de que se inicie el protocolo de enlace TLS). Si el servidor solicita el certificado de cliente, Windows responderá con el certificado proporcionado.

Este es un fragmento de código que muestra cómo implementar esto:

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

Proporcionar credenciales de autenticación a un servicio web

Las API de red que permiten a las aplicaciones interactuar con servicios web seguros proporcionan sus propios métodos para inicializar un cliente o establecer un encabezado de solicitud con credenciales de autenticación de servidor y proxy. Cada método se establece con un objeto PasswordCredential que indica un nombre de usuario, una contraseña y el recurso para el que se usan estas credenciales. En la tabla siguiente se proporciona una asignación de estas API:

WebSockets MessageWebSocketControl.ServerCredential
MessageWebSocketControl.ProxyCredential
StreamWebSocketControl.ServerCredential
StreamWebSocketControl.ProxyCredential
Transferencia en segundo plano BackgroundDownloader.ServerCredential
BackgroundDownloader.ProxyCredential
BackgroundUploader.ServerCredential
BackgroundUploader.ProxyCredential
Sindicación SyndicationClient(PasswordCredential)
SyndicationClient.ServerCredential
SyndicationClient.ProxyCredential
AtomPub AtomPubClient(PasswordCredential)
AtomPubClient.ServerCredential
AtomPubClient.ProxyCredential

Control de excepciones de red

En la mayoría de las áreas de programación, una excepción indica un problema o error significativo, causado por algún error en el programa. En la programación de red, hay un origen adicional para las excepciones: la propia red y la naturaleza de las comunicaciones de red. Las comunicaciones de red son intrínsecamente poco confiables y propensas a errores inesperados. Para cada una de las formas en que tu aplicación utiliza la red, debes mantener cierta información de estado; y el código de tu aplicación debe gestionar las excepciones de red actualizando esa información de estado e iniciando la lógica adecuada para que tu aplicación restablezca la comunicación o la reintente tras un fallo de comunicación.

Cuando las aplicaciones universales de Windows inician una excepción, el controlador de excepciones puede recuperar información más detallada sobre la causa de la excepción para comprender mejor el error y tomar las decisiones adecuadas.

Cada proyección de lenguaje admite un método para acceder a esta información más detallada. Una excepción se proyecta como un valor HRESULT en aplicaciones universales de Windows. El archivo de inclusión Winerror.h contiene una lista muy grande de posibles valores HRESULT que incluyen errores de red.

Las API de red admiten diferentes métodos para recuperar esta información detallada sobre la causa de una excepción.

  • Algunas API proporcionan un método auxiliar que convierte el valor HRESULT de la excepción a un valor de enumeración.
  • Otras API proporcionan un método para recuperar el valor HRESULT real.