Conexión en red de juegosNetworking for games

Aprende a desarrollar e incorporar características de red en un juego DirectX.Learn how to develop and incorporate networking features into your DirectX game.

Conceptos de un vistazoConcepts at a glance

En tu juego DirectX puedes usar una variedad de características de red, ya sea un juego independiente sencillo o juegos masivos de varios jugadores.A variety of networking features can be used in your DirectX game, whether it is a simple standalone game to massively multi-player games. El uso más simple de las funciones de red sería almacenar nombres de usuario y puntuaciones del juego en un servidor de red central.The simplest use of networking would be to store user names and game scores on a central network server.

Se necesitan API para redes en los juegos de varios jugadores que usan el modelo de infraestructura (servidor de cliente o punto a punto de Internet) y también para los juegos ad hoc (punto a punto local).Networking APIs are needed in multi-player games that use the infrastructure (client-server or internet peer-to-peer) model and also by ad hoc (local peer-to-peer) games. Para juegos de varios jugadores basados en servidor, un servidor de juegos central generalmente controla la mayoría de las operaciones de juego y la aplicación de juego cliente se usa para entrada, visualización de gráficos, reproducción de audio y demás características.For server-based multi-player games, a central game server usually handles most of the game operations and the client game app is used for input, displaying graphics, playing audio, and other features. La velocidad y latencia de las transferencias de red es un factor importante para una experiencia de juego satisfactoria.The speed and latency of network transfers is a concern for a satisfactory game experience.

Para los juegos de punto a punto, la aplicación de cada jugador controla la entrada y los gráficos.For peer-to-peer games, each player's app handles the input and graphics. En la mayoría de los casos, los jugadores del juego se encuentran cerca para que la latencia de red sea menor pero siga siendo un factor importante.In most cases, the game players are located in close proximity so that network latency should be lower but is still a concern. Cómo descubrir pares y establecer una conexión es un punto importante a tener en cuenta.How to discovery peers and establish a connection becomes a concern.

Para juegos de un solo jugador, generalmente se usa un servicio o servidor web central para almacenar nombres de usuario, puntuaciones de juego y demás datos varios.For single-player games, a central Web server or service is often used to store user names, game scores, and other miscellaneous information. En estos juegos, la velocidad y la latencia de las transferencias de red no son tan importantes dado que no afectan directamente la operación de juego.In these games, the speed and latency of networking transfers is less of a concern since it doesn't directly affect game operation.

Las condiciones de la red pueden cambiar en cualquier momento. Por ello, los juegos que usan API de red deben controlar las excepciones de red que puedan producirse.Network conditions can change at any time, so any game that uses networking APIs needs to handle network exceptions that may occur. Para obtener más información sobre el control de las excepciones de red, consulta Conceptos básicos de redes.To learn more about handling network exceptions, see Networking basics.

Los firewall y proxy web son comunes y pueden afectar la capacidad de usar las características de red.Firewalls and web proxies are common and can affect the ability to use networking features. Un juego que usa la red debe estar preparado para controlar correctamente los firewall y proxy.A game that uses networking needs to be prepared to properly handle firewalls and proxies.

Para dispositivos móviles, es importante supervisar los recursos de red disponibles y actuar en consecuencia cuando esté en redes medidas donde los costes de los datos y el roaming pueden ser significativos.For mobile devices, it is important to monitor available network resources and behave accordingly when on metered networks where roaming or data costs can be significant.

El aislamiento de red forma parte del modelo de seguridad de la aplicación usado por Windows.Network isolation is part of the app security model used by Windows. Windows detecta activamente los límites de la red y aplica las restricciones de acceso a la red para el aislamiento.Windows actively discovers network boundaries and enforces network access restrictions for network isolation. Las aplicaciones deben declarar funcionalidades de aislamiento de red para definir el ámbito de acceso de red.Apps must declare network isolation capabilities in order to define the scope of network access. Sin declarar estas funcionalidades, tu aplicación no tendrá acceso a los recursos de red.Without declaring these capabilities, your app will not have access to network resources. Consulta Cómo configurar las funcionalidades de aislamiento de red para obtener más información acerca de cómo Windows aplica el aislamiento de red para las aplicaciones.To learn more about how Windows enforces network isolation for apps, see How to configure network isolation capabilities.

Consideraciones de diseñoDesign considerations

En los juegos DirectX se puede usar una variedad de API de red.A variety of networking APIs can be used in DirectX games. Por ello, es importante elegir la API correcta.So, it is important to pick the right API. Windows admite una variedad de API de red que tu aplicación puede usar para comunicarse con otros equipos y dispositivos a través de Internet o de redes privadas.Windows supports a variety of networking APIs that your app can use to communicate with other computers and devices over either the Internet or private networks. Tu primer paso es determinar qué características de red necesita tu aplicación.Your first step is to figure out what networking features your app needs.

Estas son las API de red más populares para los juegos.These are the more popular network APIs for games.

  • TCP y sockets: proporciona una conexión confiable.TCP and sockets - Provides a reliable connection. Usa TCP para las operaciones de juego que no necesitan seguridad.Use TCP for game operations that don’t need security. TCP permite que el servidor escale con facilidad. Por ello, se usa comúnmente en juegos que usan el modelo de infraestructura (servidor cliente o punto a punto de Internet).TCP allows the server to easily scale, so it is commonly used in games that use the infrastructure (client-server or internet peer-to-peer) model. TCP puede ser usado por juegos ad hoc (punto a punto local) a través de Wi-Fi Direct y Bluetooth.TCP can also be used by ad hoc (local peer-to-peer) games over Wi-Fi Direct and Bluetooth. TCP generalmente se usa para movimiento de objetos en juegos, interacción de caracteres, conversaciones de texto y demás operaciones.TCP is commonly used for game object movement, character interaction, text chat, and other operations. La clase StreamSocket proporciona un socket TCP que se puede usar en los juegos de Microsoft Store.The StreamSocket class provides a TCP socket that can be used in Microsoft Store games. La clase StreamSocket se usa con clases relacionadas en el espacio de nombres Windows::Networking::Sockets.The StreamSocket class is used with related classes in the Windows::Networking::Sockets namespace.
  • TCP y sockets que usan SSL: proporciona una conexión confiable que evita interceptaciones.TCP and sockets using SSL - Provides a reliable connection that prevents eavesdropping. Usa conexiones TCP con SSL para operaciones de juego que requieren de seguridad.Use TCP connections with SSL for game operations that need security. El cifrado y la sobrecarga de SSL agrega un coste de latencia y rendimiento. Por ello es el único que se usa cuando se necesita seguridad.The encryption and overhead of SSL adds a cost in latency and performance, so it is only used when security is needed. TCP con SSL generalmente se usa para iniciar sesión, comprar y vender activos, y crear y administrar personajes.TCP with SSL is commonly used for login, purchasing and trading assets, game character creation and management. La clase StreamSocket proporciona un socket TCP que admite SSL.The StreamSocket class provides a TCP socket that supports SSL.
  • UDP y sockets: proporciona transferencias de red no confiables con poca sobrecarga.UDP and sockets - Provides unreliable network transfers with low overhead. UDP se usa para operaciones de juego que requieren de poca latencia y pueden tolerar cierto grado de pérdida de paquetes.UDP is used for game operations that require low latency and can tolerate some packet loss. Generalmente se usa para juegos de lucha, disparos y rastreo, audio de red y conversaciones de voz.This is often used for fighting games, shooting and tracers, network audio, and voice chat. La clase DatagramSocket proporciona un socket UDP que se puede usar en los juegos de Microsoft Store.The DatagramSocket class provides a UDP socket that can be used in Microsoft Store games. La clase DatagramSocket se usa con clases relacionadas en el espacio de nombres Windows::Networking::Sockets.The DatagramSocket class is used with related classes in the Windows::Networking::Sockets namespace.
  • Cliente HTTP: proporciona una conexión confiable a servidores HTTP.HTTP Client - Provides a reliable connection to HTTP servers. El escenario de redes más común es obtener acceso a un sitio web para recuperar o almacenar datos.The most common networking scenario is to access a web site to retrieve or store information. Un ejemplo simple sería un juego que usa un sitio web para almacenar información del usuario y puntuación de juegos.A simple example would be a game that uses a website to store user information and game scores. Cuando se usa con SSL para seguridad, puede usarse un cliente HTTP para iniciar sesión, comercializar activos, administrar y crear caracteres de juego.When used with SSL for security, an HTTP client can be used for login, purchasing, trading assets, game character creation, and management. La clase HttpClient proporciona una API de cliente http moderna para su uso en Microsoft Store Games.The HttpClient class provides a modern HTTP client API for use in Microsoft Store games. La clase HttpClient se usa con clases relacionadas en el espacio de nombres Windows::Web::Http.The HttpClient class is used with related classes in the Windows::Web::Http namespace.

Administrar las excepciones de red en tu juego de DirectXHandling network exceptions in your DirectX game

Cuando se produce una excepción de red en tu juego DirectX, significa que se produjo un error o problema importante.When a network exception occurs in your DirectX game, this indicates a significant problem or failure. Las excepciones pueden producirse por muchas razones cuando se usan las API de red.Exceptions can occur for many reasons when using networking APIs. A menudo, la excepción puede producirse por cambios en la conectividad de red u otros problemas de red con el servidor o host remoto.Often, the exception can result from changes in network connectivity or other networking issues with the remote host or server.

Algunos de los motivos de las excepciones al usar API de red pueden ser los siguientes:Some causes of exceptions when using networking APIs include the following:

  • La entrada del usuario para un nombre de host o un URI contiene errores y no es válida.Input from the user for a hostname or a URI contains errors and is not valid.
  • Errores de resoluciones de nombre al buscar un URI o nombre de host.Name resolutions failures when looking up a hostname or a URi.
  • Pérdida o cambio de la conectividad de red.Loss or change in network connectivity.
  • Errores en la conexión de red al usar sockets o las API de cliente HTTP.Network connection failures using sockets or the HTTP client APIs.
  • Errores del extremo remoto o del servidor de red.Network server or remote endpoint errors.
  • Errores de red diversos.Miscellaneous networking errors.

Las excepciones a causa de errores en la red (por ejemplo, por pérdida o cambios de la conectividad, errores de conexión y errores del servidor) pueden producirse en cualquier momento.Exceptions from network errors (for example, loss or change of connectivity, connection failures, and server failures) can happen at any time. Estos errores hacen que se arrojen excepciones.These errors result in exceptions being thrown. Si tu aplicación no controla las excepciones, estas pueden ocasionar que el tiempo de ejecución finalice la aplicación.If an exception is not handled by your app, it can cause your entire app to be terminated by the runtime.

Debes escribir código para controlar las excepciones cuando llamas a la mayoría de los métodos de red asincrónicos.You must write code to handle exceptions when you call most asynchronous network methods. Algunas veces, cuando se produce una excepción, se puede reintentar un método de red para intentar solucionar el problema.Sometimes, when an exception occurs, a network method can be retried as a way to resolve the problem. Otras veces, la aplicación podría necesitar un plan para continuar sin conectividad de red usando los datos almacenados anteriormente en caché.Other times, your app may need to plan to continue without network connectivity using previously cached data.

Las aplicaciones de la Plataforma universal de Windows (UWP) por lo general arrojan una sola excepción.Universal Windows Platform (UWP) apps generally throw a single exception. Tu 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.Your exception handler can retrieve more detailed information about the cause of the exception to better understand the failure and make appropriate decisions.

Cuando se produce una excepción en un juego DirectX que es una aplicación para UWP, se puede recuperar el valor HRESULT de la causa del error.When an exception occurs in a DirectX game that is a UWP app, the HRESULT value for the cause of the error can be retrieved. El archivo de inclusión Winerror.h contiene una lista extensa de posibles valores HRESULT, que incluye errores de red.The Winerror.h include file contains a large list of possible HRESULT values that includes network errors.

Las API de red admiten distintos métodos para recuperar esta información detallada sobre la causa de una excepción.The networking APIs support different methods for retrieving this detailed information about the cause of an exception.

  • Un método para recuperar el valor HRESULT del error que provocó la excepción.A method to retrieve the HRESULT value of the error that caused the exception. La lista de posibles valores de HRESULT es grande y no especificada.The possible list of potential HRESULT values is large and unspecified. El valor HRESULT puede recuperarse al usar cualquiera de las API para redes.The HRESULT value can be retrieved when using any of the networking APIs.
  • Un método auxiliar que convierte el valor HRESULT en un valor de enumeración.A helper method that converts the HRESULT value to an enumeration value. La lista de posibles valores de enumeración es especificada y relativamente pequeña.The list of possible enumeration values is specified and relatively small. Hay un método auxiliar disponible para las clases de socket en Windows::Networking::Sockets.A helper method is available for the socket classes in the Windows::Networking::Sockets.

Excepciones en Windows.Networking.SocketsExceptions in Windows.Networking.Sockets

El constructor de la clase HostName que se usa con los sockets puede generar una excepción si la cadena pasada no es un nombre de host válido (contiene caracteres que no se pueden usar en un nombre de host).The constructor for the HostName class used with sockets can throw an exception if the string passed is not a valid hostname (contains characters that are not allowed in a host name). Si una aplicación obtiene la intervención del usuario para el HostName de una conexión del mismo nivel para juegos, el constructor debe estar en un bloque try/catch.If an app gets input from the user for the HostName for a peer connection for gaming, the constructor should be in a try/catch block. Si se genera una excepción, la aplicación podrá notificar al usuario y solicitar otro nombre de host.If an exception is thrown, the app can notify the user and request a new hostname.

Agregar código para validar una cadena para un nombre de host del usuarioAdd code to validate a string for a hostname from the user

// Define some variables at the class level.
Windows::Networking::HostName^ remoteHost;

bool isHostnameFromUser = false;
bool isHostnameValid = false;

///...

// If the value of 'remoteHostname' is set by the user in a control as input 
// and is therefore untrusted input and could contain errors. 
// If we can't create a valid hostname, we notify the user in statusText 
// about the incorrect input.

String ^hostString = remoteHostname;

try 
{
    remoteHost = ref new Windows::Networking:Host(hostString);
    isHostnameValid = true;
}
catch (InvalidArgumentException ^ex)
{
    statusText->Text = "You entered a bad hostname, please re-enter a valid hostname.";
    return;
}

isHostnameFromUser = true;

// ... Continue with code to execute with a valid hostname.

El espacio de nombres Windows.Networking.Sockets tiene enumeraciones y métodos auxiliares convenientes para controlar errores al usar sockets.The Windows.Networking.Sockets namespace has convenient helper methods and enumerations for handling errors when using sockets. Esto puede ser útil para controlar de un modo diferente excepciones de red específicas en la aplicación.This can be useful for handling specific network exceptions differently in your app.

Encontrar un error en DatagramSocket, StreamSocket o una operación StreamSocketListener hace que se arroje una excepción.An error encountered on DatagramSocket, StreamSocket, or StreamSocketListener operation results in an exception being thrown. La causa de la excepción es un valor de error representado como un valor HRESULT.The cause of the exception is an error value represented as an HRESULT value. El método SocketError.GetStatus se usa para convertir un error de red de una operación de socket en un valor de enumeración SocketErrorStatus.The SocketError.GetStatus method is used to convert a network error from a socket operation to a SocketErrorStatus enumeration value. La mayoría de los valores de enumeración SocketErrorStatus corresponden a un error devuelto por la operación de Windows Sockets nativa.Most of the SocketErrorStatus enumeration values correspond to an error returned by the native Windows sockets operation. Una aplicación puede filtrar según valores SocketErrorStatus concretos para modificar el comportamiento de la aplicación en función del motivo de la excepción.An app can filter on specific SocketErrorStatus enumeration values to modify app behavior depending on the cause of the exception.

Para los errores de validación de parámetros, una aplicación también puede usar el HRESULT de la excepción para obtener información más detallada del error que causó la excepción.For parameter validation errors, an app can also use the HRESULT from the exception to learn more detailed information about the error that caused the exception. Los valores posibles de HRESULT se enumeran en el archivo de encabezado Winerror.h.Possible HRESULT values are listed in the Winerror.h header file. Para la mayoría de los errores de validación de parámetros, el HRESULT devuelto es E _ INVALIDARG.For most parameter validation errors, the HRESULT returned is E_INVALIDARG.

Agregar código para controlar excepciones cuando se intenta hacer una conexión de socket de secuenciasAdd code to handle exceptions when trying to make a stream socket connection

using namespace Windows::Networking;
using namespace Windows::Networking::Sockets;
    
    // Define some more variables at the class level.

    bool isSocketConnected = false
    bool retrySocketConnect = false;

    // The number of times we have tried to connect the socket.
    unsigned int retryConnectCount = 0;

    // The maximum number of times to retry a connect operation.
    unsigned int maxRetryConnectCount = 5; 
    ///...

    // We pass in a valid remoteHost and serviceName parameter.
    // The hostname can contain a name or an IP address.
    // The servicename can contain a string or a TCP port number.

    StreamSocket ^ socket = ref new StreamSocket();
    SocketErrorStatus errorStatus; 
    HResult hr;

    // Save the socket, so any subsequent steps can use it.
    CoreApplication::Properties->Insert("clientSocket", socket);

    // Connect to the remote server. 
    create_task(socket->ConnectAsync(
            remoteHost,
            serviceName,
            SocketProtectionLevel::PlainSocket)).then([this] (task<void> previousTask)
    {
        try
        {
            // Try getting all exceptions from the continuation chain above this point.
            previousTask.get();

            isSocketConnected = true;
            // Mark the socket as connected. We do not really care about the value of the property, but the mere 
            // existence of  it means that we are connected.
            CoreApplication::Properties->Insert("connected", nullptr);
        }
        catch (Exception^ ex)
        {
            hr = ex.HResult;
            errorStatus = SocketStatus::GetStatus(hr); 
            if (errorStatus != Unknown)
            {
                                                                switch (errorStatus) 
                   {
                    case HostNotFound:
                        // If the hostname is from the user, this may indicate a bad input.
                        // Set a flag to ask the user to re-enter the hostname.
                        isHostnameValid = false;
                        return;
                        break;
                    case ConnectionRefused:
                        // The server might be temporarily busy.
                        retrySocketConnect = true;
                        return;
                        break; 
                    case NetworkIsUnreachable: 
                        // This could be a connectivity issue.
                        retrySocketConnect = true;
                        break;
                    case UnreachableHost: 
                        // This could be a connectivity issue.
                        retrySocketConnect = true;
                        break;
                    case NetworkIsDown: 
                        // This could be a connectivity issue.
                        retrySocketConnect = true;
                        break;
                    // Handle other errors. 
                    default: 
                        // The connection failed and no options are available.
                        // Try to use cached data if it is available. 
                        // You may want to tell the user that the connect failed.
                        break;
                }
                }
                else 
                {
                    // Received an Hresult that is not mapped to an enum.
                    // This could be a connectivity issue.
                    retrySocketConnect = true;
                }
            }
        });
    }

Excepciones en Windows.Web.HttpExceptions in Windows.Web.Http

El constructor de la clase Windows::Foundation::Uri usado con Windows::Web::Http::HttpClient puede arrojar una excepción si se pasa una cadena con un URI no válido (contiene caracteres no permitidos en un URI).The constructor for the Windows::Foundation::Uri class used with Windows::Web::Http::HttpClient can throw an exception if the string passed is not a valid URI (contains characters that are not allowed in a URI). En C++, no hay ningún método para probar y analizar una cadena en un URI.In C++, there is no method to try and parse a string to a URI. Si una aplicación obtiene la entrada del usuario para Windows:: Foundation:: URI, el constructor debe estar en un bloque try/catch.If an app gets input from the user for the Windows::Foundation::Uri, the constructor should be in a try/catch block. Si se arroja una excepción, la aplicación puede notificar al usuario y solicitar un nuevo URI.If an exception is thrown, the app can notify the user and request a new URI.

La aplicación también debe comprobar que el esquema en el URI sea HTTP o HTTPS, dado que estos son los únicos esquemas admitidos por Windows::Web::Http::HttpClient.Your app should also check that the scheme in the URI is HTTP or HTTPS since these are the only schemes supported by the Windows::Web::Http::HttpClient.

Agregar código para validar una cadena para un URI del usuarioAdd code to validate a string for a URI from the user

    // Define some variables at the class level.
    Windows::Foundation::Uri^ resourceUri;

    bool isUriFromUser = false;
    bool isUriValid = false;

    ///...

    // If the value of 'inputUri' is set by the user in a control as input 
    // and is therefore untrusted input and could contain errors. 
    // If we can't create a valid hostname, we notify the user in statusText 
    // about the incorrect input.

    String ^uriString = inputUri;

    try 
    {
        isUriValid = false;
        resourceUri = ref new Windows::Foundation:Uri(uriString);

        if (resourceUri->SchemeName != "http" && resourceUri->SchemeName != "https")
        {
            statusText->Text = "Only 'http' and 'https' schemes supported. Please re-enter URI";
            return;
        }
        isUriValid = true;
    }
    catch (InvalidArgumentException ^ex)
    {
        statusText->Text = "You entered a bad URI, please re-enter Uri to continue.";
        return;
    }

    isUriFromUser = true;


    // ... Continue with code to execute with a valid URI.

El espacio de nombres Windows::Web::Http no tiene una función de conveniencia.The Windows::Web::Http namespace lacks a convenience function. Por lo tanto, una aplicación que usa HttpClient y otras clases de este espacio de nombres necesita usar el valor HRESULT .So, an app using HttpClient and other classes in this namespace needs to use the HRESULT value.

En las aplicaciones con C++, Platform::Exception representa un error durante la ejecución de la aplicación cuando se produce una excepción.In apps using C++, the Platform::Exception represents an error during app execution when an exception occurs. La propiedad Platform::Exception::HResult devuelve el valor HRESULT asignado a la excepción concreta.The Platform::Exception::HResult property returns the HRESULT assigned to the specific exception. La propiedad Platform::Exception::Message devuelve la cadena proporcionada por el sistema asociada con el valor HRESULT.The Platform::Exception::Message property returns the system-provided string that is associated with the HRESULT value. Los valores posibles de HRESULT se enumeran en el archivo de encabezado Winerror.h.Possible HRESULT values are listed in the Winerror.h header file. Una aplicación puede filtrar según valores HRESULT concretos para modificar el comportamiento de la aplicación en función del motivo de la excepción.An app can filter on specific HRESULT values to modify app behavior depending on the cause of the exception.

Para la mayoría de los errores de validación de parámetros, el HRESULT devuelto es E _ INVALIDARG.For most parameter validation errors, the HRESULT returned is E_INVALIDARG. Para algunas llamadas a métodos no válidas, el valor de HRESULT devuelto es E_ILLEGAL_METHOD_CALL.For some illegal method calls, the HRESULT returned is E_ILLEGAL_METHOD_CALL.

Agregar código para controlar excepciones cuando se intenta usar HttpClient para conectarse a un servidor HTTPAdd code to handle exceptions when trying to use HttpClient to connect to an HTTP server

using namespace Windows::Foundation;
using namespace Windows::Web::Http;
    
    // Define some more variables at the class level.

    bool isHttpClientConnected = false
    bool retryHttpClient = false;

    // The number of times we have tried to connect the socket
    unsigned int retryConnectCount = 0;

    // The maximum number of times to retry a connect operation.
    unsigned int maxRetryConnectCount = 5; 
    ///...

    // We pass in a valid resourceUri parameter.
    // The URI must contain a scheme and a name or an IP address.

    HttpClient ^ httpClient = ref new HttpClient();
    HResult hr;

    // Save the httpClient, so any subsequent steps can use it.
    CoreApplication::Properties->Insert("httpClient", httpClient);

    // Send a GET request to the HTTP server. 
    create_task(httpClient->GetAsync(resourceUri)).then([this] (task<void> previousTask)
    {
        try
        {
            // Try getting all exceptions from the continuation chain above this point.
            previousTask.get();

            isHttpClientConnected = true;
            // Mark the HttClient as connected. We do not really care about the value of the property, but the mere 
            // existence of  it means that we are connected.
            CoreApplication::Properties->Insert("connected", nullptr);
        }
        catch (Exception^ ex)
        {
            hr = ex.HResult;
                                                switch (errorStatus) 
               {
                case WININET_E_NAME_NOT_RESOLVED:
                    // If the Uri is from the user, this may indicate a bad input.
                    // Set a flag to ask user to re-enter the Uri.
                    isUriValid = false;
                    return;
                    break;
                case WININET_E_CANNOT_CONNECT:
                    // The server might be temporarily busy.
                    retryHttpClientConnect = true;
                    return;
                    break; 
                case WININET_E_CONNECTION_ABORTED: 
                    // This could be a connectivity issue.
                    retryHttpClientConnect = true;
                    break;
                case WININET_E_CONNECTION_RESET: 
                    // This could be a connectivity issue.
                    retryHttpClientConnect = true;
                    break;
                case INET_E_RESOURCE_NOT_FOUND: 
                    // The server cannot locate the resource specified in the uri.
                    // If the Uri is from user, this may indicate a bad input.
                    // Set a flag to ask the user to re-enter the Uri
                    isUriValid = false;
                    return;
                    break;
                // Handle other errors. 
                default: 
                    // The connection failed and no options are available.
                    // Try to use cached data if it is available. 
                    // You may want to tell the user that the connect failed.
                    break;
            }
            else 
            {
                // Received an Hresult that is not mapped to an enum.
                // This could be a connectivity issue.
                retrySocketConnect = true;
            }
        }
    });

Otros recursosOther resources

ReferenciaReference

Aplicaciones de ejemploSample apps