ネットワークの基本Networking basics

ネットワーク対応アプリで実行する必要がある事柄について説明します。Things you must do for any network-enabled app.

機能Capabilities

ネットワークを使うには、アプリ マニフェストに適切な機能要素を追加する必要があります。In order to use networking, you must add appropriate capability elements to your app manifest. アプリ マニフェストにネットワーク機能が指定されていない場合、アプリはネットワーク機能を持たないため、ネットワークへの接続は失敗します。If no network capability is specified in your app's manifest, your app will have no networking capability, and any attempt to connect to the network will fail.

最もよく使われるネットワーク機能を次に示します。The following are the most-used networking capabilities.

機能Capability 説明Description
internetClientinternetClient インターネットや、公共の場所のネットワーク (空港、喫茶店など) への出力方向のアクセスを提供します。Provides outbound access to the Internet and networks in public places, like airports and coffee shop. インターネットにアクセスする必要があるほとんどのアプリは、この機能を使います。Most apps that require Internet access should use this capability.
internetClientServerinternetClientServer インターネットや、公共の場所のネットワーク (空港、喫茶店など) からの入力方向と出力方向のネットワーク アクセスをアプリに提供します。Gives the app inbound and outbound network access from the Internet and networks in public places like airports and coffee shops.
privateNetworkClientServerprivateNetworkClientServer ユーザーの信頼する場所 (自宅、職場など) において、入力方向と出力方向のネットワーク アクセスをアプリに提供します。Gives the app inbound and outbound network access at the user's trusted places, like home and work.

特定の状況では、上記以外の機能がアプリで必要になることがあります。There are other capabilities that might be necessary for your app, in certain circumstances.

機能Capability 説明Description
enterpriseAuthenticationenterpriseAuthentication ドメイン資格情報を必要とするネットワーク リソースにアプリが接続できるようにします。Allows an app to connect to network resources that require domain credentials. たとえば、プライベート イントラネットの SharePoint サーバーからデータを取得するアプリが該当します。For example, an app that retrieves data from SharePoint servers on a private Intranet. この機能を使うと、資格情報を必要とするネットワーク上のリソースに、自分の資格情報を使ってアクセスすることができます。With this capability your credentials can be used to access network resources on a network that requires credentials. この機能を持ったアプリは、ネットワーク上でユーザーを偽装することができます。An app with this capability can impersonate you on the network. 認証プロキシ経由でのインターネットへのアクセスをアプリに許可する手段として、この機能は必要ありません。You don't need this capability in order to allow your app to access the Internet via an authenticating proxy.

詳細については、制限付き機能Enterprise 機能のシナリオについてのドキュメントを参照してください。For more details, see the documentation for the Enterprise capability scenario in Restricted capabilities.
proximityproximity コンピューターときわめて近い場所にあるデバイスとの近距離近接通信で必要となります。Required for near-field proximity communication with devices in close proximity to the computer. 近距離近接通信は、近くのデバイス上のアプリケーションに接続したりデータを送ったりするときに使われます。Near-field proximity may be used to send or connect with an application on a nearby device.

この機能を有効にすると、アプリは、ユーザーの同意に基づいて相手を招待したり招待に応じたりしながら、ネットワークにアクセスし、きわめて近い場所にあるデバイスに接続することができます。This capability allows an app to access the network to connect to a device in close proximity, with user consent to send an invite or accept an invite.
sharedUserCertificatessharedUserCertificates ソフトウェア証明書とハードウェア証明書 (スマート カード証明書など) にアプリがアクセスできるようにします。This capability allows an app to access software and hardware certificates, such as smart card certificates. この機能が実行時に呼び出されると、ユーザーは、カードの挿入や証明書の選択などの行動をとる必要があります。When this capability is invoked at runtime, the user must take action, such as inserting a card or selecting a certificate.

この機能では、ソフトウェア証明書やハードウェア証明書、スマート カードが、アプリでの身分証明に使われます。With this capability, your software and hardware certificates or a smart card are used for identification in the app. この機能は、企業や銀行、行政サービスで身分証明に使うことができます。This capability may be used by your employer, bank, or government services for identification.

アプリがフォア グラウンドにないときの通信Communicating when your app is not in the foreground

バックグラウンド タスクによるアプリのサポート」には、アプリがフォアグラウンドでないときにバックグラウンド タスクを使って処理を実行する方法に関する一般的な情報が含まれています。Support your app with background tasks contains general information about using background tasks to do work when your app is not in the foreground. 具体的には、アプリがフォアグラウンド アプリでないときにネットワーク経由でそのアプリのデータが到着した場合は、到着通知を受け取るための特別な手順のコードを実行する必要があります。More specifically, your code must take special steps to be notified when it is not the current foreground app and data arrives over the network for it. Windows 8 では、このためにコントロール チャネル トリガーを使っていました。これらのトリガーは、Windows 10 でも引き続きサポートされます。You used Control Channel Triggers for this purpose in Windows 8, and they are still supported in Windows 10. コントロール チャネル トリガーの使い方について詳しくはここをご覧ください。Full information about using Control Channel Triggers is available here. Windows 10 の新しいテクノロジでは、プッシュ対応ストリーム ソケットなどのいくつかのシナリオでオーバーヘッドが小さい優れた機能であるソケット ブローカーとソケット アクティビティ トリガーを利用できます。A new technology in Windows 10 provides better functionality with lower overhead for some scenarios, such as push-enabled stream sockets: the socket broker and socket activity triggers.

アプリで DatagramSocketStreamSocket、または StreamSocketListener を使っている場合は、開いているソケットの所有権をシステムが提供するソケット ブローカーに移譲した後、フォアグラウンドから離れるか、アプリを終了できます。If your app uses DatagramSocket, StreamSocket, or StreamSocketListener, then your app can transfer ownership of an open socket to a socket broker provided by the system, and then leave the foreground, or even terminate. 移譲されたソケットで接続が行われるか、そのソケットでトラフィックが到着すると、アプリまたは指定されたバックグラウンド タスクがアクティブ化します。When a connection is made on the transferred socket, or traffic arrives on that socket, then your app or its designated background task are activated. アプリが実行されていない場合は、開始されます。If your app is not running, it is started. その後、ソケット ブローカーは、SocketActivityTrigger を使って、新しいトラフィックが到着していることをアプリに通知します。The socket broker then notifies your app using a SocketActivityTrigger that new traffic has arrived. アプリは、ソケット ブローカーからソケットを取り戻し、そのソケットのトラフィックを処理します。Your app reclaims the socket from the socket broker and process the traffic on the socket. つまり、アプリがネットワーク トラフィックをアクティブに処理していないときに消費するシステム リソースが非常に少なくなります。This means that your app consumes far less system resources when it is not actively processing network traffic.

ソケット ブローカーはコントロール チャネル トリガーと同じ機能を少ない制限と小さなメモリ使用量で提供するため、ソケット ブローカーの目的は、適切な場所でコントロール チャネル トリガーと交代することです。The socket broker is intended to replace Control Channel Triggers where it is applicable, because it provides the same functionality, but with fewer restrictions and a smaller memory footprint. ソケット ブローカーは、ロック画面に表示するアプリ以外のアプリで使うことができ、電話でも他のデバイスと同じように使うことができます。Socket broker can be used by apps that are not lock screen apps, and it is used the same way on phones as on other devices. ソケット ブローカーによってアクティブ化するために、トラフィックの到着時にアプリが実行されている必要はありません。Apps need not be running when traffic arrives in order to be activated by the socket broker. さらに、ソケット ブローカーは、TCP ソケットでのリッスンをサポートします。これはコントロール チャネル トリガーではサポートされていません。And the socket broker supports listening on TCP sockets, which Control Channel Triggers do not support.

ネットワーク トリガーの選択Choosing a network trigger

どちらの種類のトリガーが適しているかを判断するいくつかのシナリオがあります。There are some scenarios where either kind of trigger would be suitable. アプリで使うトリガーの種類を選択するときは、次のアドバイスを検討してください。When you are choosing which kind of trigger to use in your app, consider the following advice.

ソケット ブローカーの使い方の説明と例については、「バックグラウンドでのネットワーク通信」をご覧ください。For details and examples of how to use the socket broker, see Network communications in the background.

セキュリティ保護された接続Secured connections

Secure Sockets Layer (SSL) とより新しいトランスポート層セキュリティ (TLS) は、ネットワーク通信の認証と暗号化を実現するように設計された暗号化プロトコルです。Secure Sockets Layer (SSL) and the more recent Transport Layer Security (TLS) are cryptographic protocols designed to provide authentication and encryption for network communication. これらのプロトコルは、ネットワーク データの送受信時に傍受や改ざんを防ぐように設計されています。These protocols are designed to prevent eavesdropping and tampering when sending and receiving network data. これらのプロトコルでは、クライアント/サーバー モデルを使ってプロトコル交換が行われます。These protocols use a client-server model for the protocol exchanges. また、デジタル証明書と証明機関を使って、サーバーが本物であることが確認されます。These protocols also use digital certificates and certificate authorities to verify that the server is who it claims to be.

セキュリティが確保されたソケット接続の作成Creating secure socket connections

StreamSocket オブジェクトは、クライアントとサーバー間の通信に SSL/TLS を使うように構成できます。A StreamSocket object can be configured to use SSL/TLS for communications between the client and the server. この SSL/TLS のサポートは、SSL/TLS ネゴシエーションで StreamSocket オブジェクトをクライアントとして使うことに制限されます。This support for SSL/TLS is limited to using the StreamSocket object as the client in the SSL/TLS negotiation. サーバーとしての SSL/TLS ネゴシエーションは StreamSocket クラスで実装されていないため、着信接続を受信したときに StreamSocketListener によって作成された StreamSocket と共に SSL/TLS を使うことはできません。You cannot use SSL/TLS with the StreamSocket created by a StreamSocketListener when incoming communications are received, because SSL/TLS negotiation as a server is not implemented by the StreamSocket class.

StreamSocket 接続のセキュリティを確保するには 2 つの方法があります。There are two ways to secure a StreamSocket connection with SSL/TLS:

  • ConnectAsync - ネットワーク サービスへの最初の接続を確立してすぐに、すべての通信で SSL/TLS を使うようにネゴシエートします。ConnectAsync - Make the initial connection to a network service and negotiate immediately to use SSL/TLS for all communications.
  • UpgradeToSslAsync - 最初に暗号化なしでネットワーク サービスに接続します。UpgradeToSslAsync - Connect initially to a network service without encryption. アプリでデータが送受信される場合があります。The app may send or receive data. その後、以降のすべての通信で SSL/TLS を使うように接続をアップグレードします。Then, upgrade the connection to use SSL/TLS for all further communications.

SocketProtectionLevel は、アプリが接続を確立またはアップグレードする際に必要なソケット保護レベルを指定します。The SocketProtectionLevel specifies the desired socket protection level the app wants to establish or upgrade the connection with. ただし、確立される接続の最終的な保護レベルは接続の両方のエンドポイント間のネゴシエーション プロセスで決まります。However, the eventual protection level of the established connection is determined in a negotiation process between both endpoints of the connection. 指定した保護レベルは、相手のエンドポイントでより低いレベルが要求されている場合、より低くなることがあります。The result can be a lower protection level than the one you specified, if the other endpoint requests a lower level.

非同期操作が正常に完了した後、ConnectAsync または UpgradeToSslAsync の呼び出しで要求された保護レベルは、StreamSocketinformation.ProtectionLevel プロパティで取得できます。After the async operation has completed successfully, you can retrieve the requested protection level used in the ConnectAsync or UpgradeToSslAsync call through the StreamSocketinformation.ProtectionLevel property. ただし、これは接続で実際に使用されている保護レベルを反映していません。However, this does not reflect the actual protection level the connection is using.

注意

コードでは、特定の保護レベルの使用に暗黙的に依存しないように、つまり特定のセキュリティ レベルの既定での使用を前提にしないようにしてください。Your code should not implicitly depend on using a particular protection level, or on the assumption that a given security level is used by default. セキュリティ環境は変わり続けており、プロトコルと既定の保護レベルは、既知の弱点のあるプロトコルの使用を避けるように、刻々と変更されています。The security landscape changes constantly, and protocols and default protection levels change over time in order to avoid the use of protocols with known weaknesses. 既定値は、個々のコンピューターの構成、つまりインストールされているソフトウェアや適用されているパッチによって異なることがあります。Defaults can vary depending on individual machine configuration, or on which software is installed and which patches have been applied. アプリが特定のセキュリティ レベルの使用に依存する場合は、明示的にそのレベルを指定したうえで、実際にそのレベルを使って接続が確立されたことを確認する必要があります。If your app depends on the use of a particular security level, then you must explicitly specify that level and then check to be sure that it is actually in use on the established connection.

ConnectAsync の使用Use ConnectAsync

ConnectAsync は、ネットワーク サービスへの最初の接続を確立して、すぐにすべての通信で SSL/TLS を使うようにネゴシエートするのに使えます。ConnectAsync can be used to establish the initial connection with a network service and then negotiate immediately to use SSL/TLS for all communications. protectionLevel パラメーターを渡すことができる ConnectAsync メソッドは 2 つあります。There are two ConnectAsync methods that support passing a protectionLevel parameter:

先ほどのいずれかの ConnectAsync メソッドを呼び出すときに protectionLevel パラメーターが Windows.Networking.Sockets.SocketProtectionLevel.Ssl に設定されていると、StreamSocket による通信の暗号化に SSL/TLS を使う必要があります。If the protectionLevel parameter is set to Windows.Networking.Sockets.SocketProtectionLevel.Ssl when calling either of the above ConnectAsync methods, the StreamSocket must will be established to use SSL/TLS for encryption. この値を指定すると暗号化が必要になり、NULL 暗号を使うことはできません。This value requires encryption and never allows a NULL cipher to be used.

これらの ConnectAsync メソッドで使う一般的な手順は同じです。The normal sequence to use with one of these ConnectAsync methods is the same.

  • StreamSocket を作成します。Create a StreamSocket.
  • ソケットの詳細オプションが必要な場合は、StreamSocket.Control プロパティを使って、StreamSocket オブジェクトに関連付けられている StreamSocketControl インスタンスを取得します。If an advanced option on the socket is needed, use the StreamSocket.Control property to get the StreamSocketControl instance associated with a StreamSocket object. StreamSocketControl のプロパティを設定します。Set a property on the StreamSocketControl.
  • 上記のいずれかの ConnectAsync メソッドを呼び出し、リモートの宛先に接続する操作を開始してすぐに、SSL/TLS の使用をネゴシエートします。Call one of the above ConnectAsync methods to start an operation to connect to a remote destination and immediately negotiate the use of SSL/TLS.
  • ConnectAsync を使って実際にネゴシエートされる SSL の強度は、非同期操作の成功後に取得される StreamSocketinformation.ProtectionLevel プロパティによって決まります。The SSL strength actually negotiated using ConnectAsync can be determined by getting the StreamSocketinformation.ProtectionLevel property after the async operation has completed successfully.

次の例では、StreamSocket を作り、ネットワーク サービスへの接続を確立してすぐに、SSL/TLS を使うようにネゴシエートします。The following example creates a StreamSocket and tries to establish a connection to the network service and negotiate immediately to use SSL/TLS. ネゴシエーションに成功すると、クライアントとネットワーク サーバー間で StreamSocket を使うすべてのネットワーク通信が暗号化されます。If the negotiation is successful, all network communication using the StreamSocket between the client the network server will be encrypted.

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

UpgradeToSslAsync の使用Use UpgradeToSslAsync

コードで UpgradeToSslAsync を使うときは、ネットワーク サービスへの最初の接続を暗号化なしで確立します。When your code uses UpgradeToSslAsync, it first establishes a connection to a network service without encryption. アプリでデータが送受信される可能性があるため、以降のすべての通信で SSL/TLS を使うように接続をアップグレードします。The app may send or receive some data, then upgrade the connection to use SSL/TLS for all further communications.

UpgradeToSslAsync メソッドは 2 つのパラメーターを受け取ります。The UpgradeToSslAsync method takes two parameters. protectionLevel パラメーターは、目的の保護レベルを示します。The protectionLevel parameter indicates the protection level desired. validationHostName パラメーターは、SSL へのアップグレード時の検証に使われるリモート ネットワークの宛先のホスト名です。The validationHostName parameter is the hostname of the remote network destination that is used for validation when upgrading to SSL. 通常、validationHostName は、アプリが最初に接続を確立するときに使ったホスト名と同じです。Normally the validationHostName would be the same hostname that the app used to initially establish the connection. UpgradeToSslAsync を呼び出すときに protectionLevel パラメーターが Windows.System.Socket.SocketProtectionLevel.Ssl に設定されていると、StreamSocket による以降の通信の暗号化に SSL/TLS を使う必要があります。If the protectionLevel parameter is set to Windows.System.Socket.SocketProtectionLevel.Ssl when calling UpgradeToSslAsync, the StreamSocket must use the SSL/TLS for encryption on further communications over the socket. この値を指定すると暗号化が必要になり、NULL 暗号を使うことはできません。This value requires encryption and never allows a NULL cipher to be used.

UpgradeToSslAsync メソッドで使う一般的な手順は次のとおりです。The normal sequence to use with the UpgradeToSslAsync method is as follows:

次の例では、StreamSocket を作り、ネットワーク サービスへの接続を確立して最初のデータを送って、SSL/TLS を使うようにネゴシエートします。The following example creates a StreamSocket, tries to establish a connection to the network service, sends some initial data, and then negotiates to use SSL/TLS. ネゴシエーションに成功すると、クライアントとネットワーク サーバー間で StreamSocket を使うすべてのネットワーク通信が暗号化されます。If the negotiation is successful, all network communication using the StreamSocket between the client and the network server will be encrypted.

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

セキュリティが確保された WebSocket 接続の作成Creating secure WebSocket connections

従来のソケット接続と同様に、StreamWebSocketMessageWebSocket の機能を UWP アプリで使う際に、トランスポート層セキュリティ (TLS)/Secure Sockets Layer (SSL) を使って WebSocket 接続を暗号化することもできます。Like traditional socket connections, WebSocket connections can also be encrypted with Transport Layer Security (TLS)/Secure Sockets Layer (SSL) when using the StreamWebSocket and MessageWebSocket features for a UWP app. ほとんどの場合、WebSocket 接続にはセキュリティを確保する必要があります。In most cases you'll want to use a secure WebSocket connection. 多くのプロキシは、暗号化されていない WebSocket 接続を拒否するため、接続の成功率が高くなります。This will increase the chances that your connection will succeed, as many proxies will reject unencrypted WebSocket connections.

セキュリティが確保されたソケット接続を作成したりネットワーク サービスへとアップグレードする方法の例については、「TLS/SSL を使って WebSocket 接続のセキュリティを確保する方法」をご覧ください。For examples of how to create, or upgrade to, a secure socket connection to a network service, see How to secure WebSocket connections with TLS/SSL.

最初のハンドシェークを完了するために、サーバーでは TLS/SSL 暗号化だけでなく Sec-WebSocket-Protocol ヘッダー値を要求することもあります。In addition to TLS/SSL encryption, a server may require a Sec-WebSocket-Protocol header value to complete the initial handshake. この値は StreamWebSocketInformation.Protocol プロパティと MessageWebSocketInformation.Protocol プロパティで表され、接続のプロトコル バージョンを示し、開いているハンドシェークとその後に交換されるデータをサーバーが正しく解釈できるようにします。This value, represented by the StreamWebSocketInformation.Protocol and MessageWebSocketInformation.Protocol properties, indicate the protocol version of the connection and enables the server to correctly interpret the opening handshake and the data being exchanged afterwards. このプロトコル情報を使うと、サーバーが着信するデータを安全な方法で解釈できないような状況になったときに、接続を閉じることができます。Using this protocol information, if at any point if the server cannot interpret the incoming data in a safe manner the connection can be closed.

クライアントからの最初の要求にこの値が含まれていない場合、または含まれている値がサーバーで想定されるものと一致しない場合は、WebSocket ハンドシェーク エラーでサーバーから想定される値がクライアントに送信されます。If the initial request from the client either does not contain this value, or provides a value that doesn't match what the server expects, the expected value is sent from the server to the client on WebSocket handshake error.

認証Authentication

ネットワーク経由で接続するときに、認証資格情報を提供する方法。How to provide authentication credentials when connecting over the network.

StreamSocket クラスによるクライアント証明書の提供Providing a client certificate with the StreamSocket class

Windows.Networking.StreamSocket クラスは、SSL/TLS を使ったアプリの接続先サーバーの認証をサポートします。The Windows.Networking.StreamSocket class supports using SSL/TLS to authenticate the server the app is talking to. 場合によっては、アプリは、TLS クライアント証明書を使って自身をサーバーに対して認証する必要があります。In certain cases, the app also needs to authenticate itself to the server using a TLS client certificate. Windows 10 では、クライアント証明書を StreamSocket.Control オブジェクトに提供できます (これは TLS ハンドシェイクが開始される前に設定する必要があります)。In Windows 10, you can provide a client certificate on the StreamSocket.Control object (this must be set before the TLS handshake is started). サーバーがクライアント証明書を要求した場合、Windows が提供された証明書を使って応答します。If the server requests the client certificate, Windows will respond with the certificate provided.

これを実装する方法を示すコード スニペットを次に示します。Here is a code snippet showing how to implement this:

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

Web サービスへの認証資格情報の提供Providing authentication credentials to a web service

Networking API は、セキュリティが確保された Web サービスとアプリが連携できるようにします。この API のそれぞれが、サーバーとプロキシの認証資格情報を使ってクライアントの初期化または要求ヘッダーの設定を行う独自のメソッドを提供します。The networking APIs that enable apps to interact with secure web services each provide their own methods to either initialize a client or set a request header with server and proxy authentication credentials. 各メソッドは、PasswordCredential オブジェクトを使って設定されます。このオブジェクトは、ユーザー名、パスワード、それぞれの資格情報が使われるリソースを示します。Each method is set with a PasswordCredential object that indicates a user name, password, and the resource for which these credentials are used. 次の表では、これらの API のマッピングについて説明します。The following table provides a mapping of these APIs:

WebSocketWebSockets MessageWebSocketControl.ServerCredentialMessageWebSocketControl.ServerCredential
MessageWebSocketControl.ProxyCredentialMessageWebSocketControl.ProxyCredential
StreamWebSocketControl.ServerCredentialStreamWebSocketControl.ServerCredential
StreamWebSocketControl.ProxyCredentialStreamWebSocketControl.ProxyCredential
バックグラウンド転送Background Transfer BackgroundDownloader.ServerCredentialBackgroundDownloader.ServerCredential
BackgroundDownloader.ProxyCredentialBackgroundDownloader.ProxyCredential
BackgroundUploader.ServerCredentialBackgroundUploader.ServerCredential
BackgroundUploader.ProxyCredentialBackgroundUploader.ProxyCredential
配信Syndication SyndicationClient(PasswordCredential) SyndicationClient(PasswordCredential)
SyndicationClient.ServerCredentialSyndicationClient.ServerCredential
SyndicationClient.ProxyCredentialSyndicationClient.ProxyCredential
AtomPubAtomPub AtomPubClient(PasswordCredential) AtomPubClient(PasswordCredential)
AtomPubClient.ServerCredentialAtomPubClient.ServerCredential
AtomPubClient.ProxyCredentialAtomPubClient.ProxyCredential

ネットワーク例外を処理するHandling network exceptions

ほとんどのプログラミング領域では、例外は、プログラムの不具合によって発生した重大な問題やエラーを示します。In most areas of programming, an exception indicates a significant problem or failure, caused by some flaw in the program. ネットワーク プログラミングでは、さらに、ネットワークそのものとネットワーク通信の特性という、例外の発生源があります。In network programming, there is an additional source for exceptions: the network itself, and the nature of network communications. ネットワーク通信は、本質的に信頼性が低く、予期しない障害が発生する傾向があります。Network communications are inherently unreliable and prone to unexpected failure. アプリでネットワークを使う方法のそれぞれについて、状態情報を維持する必要があります。アプリのコードは、その状態情報を更新し、通信エラーが発生したときに接続を再び確立するか再試行する適切なロジックを開始することで、ネットワーク例外を処理する必要があります。For each of the ways your app uses networking, you must maintain some state information; and your app code must handle network exceptions by updating that state information and initiating appropriate logic for your app to re-establish or retry communication failures.

ユニバーサル Windows アプリで例外がスローされると、例外ハンドラーは例外の原因についての詳しい情報を取得することでエラーの内容を理解して適切な判断を下すことができます。When Universal Windows apps throw an exception, your exception handler can retrieve more detailed information on the cause of the exception to better understand the failure and make appropriate decisions.

各言語のプロジェクションは、この詳しい情報にアクセスするためのメソッドをサポートしています。Each language projection supports a method to access this more detailed information. 例外は、ユニバーサル Windows アプリの HRESULT 値としてプロジェクションされます。An exception projects as an HRESULT value in Universal Windows apps. Winerror.h インクルード ファイルには、ネットワーク エラーを含む、出力される可能性がある HRESULT 値の大きなリストが格納されています。The Winerror.h include file contains a very large list of possible HRESULT values that includes network errors.

Networking API は、例外の原因についての詳しい情報を取得するために、他のメソッドをサポートしています。The networking APIs support different methods for retrieving this detailed information on the cause of an exception.

  • 一部の API には、例外の HRESULT 値を列挙値に変換するヘルパー メソッドがあります。Some APIs provide a helper method that converts the HRESULT value from the exception to an enumeration value.
  • その他の API には、実際の HRESULT 値を取得するメソッドがあります。Other APIs provide a method to retrieve the actual HRESULT value.