ソケット操作にタイムアウトを設定する方法 (HTML)

[ この記事は、Windows ランタイム アプリを作成する Windows 8.x および Windows Phone 8.x 開発者を対象としています。Windows 10 向けの開発を行っている場合は、「最新のドキュメント」をご覧ください]

このトピックでは、Windows ランタイム アプリのネットワーク ソケット操作にタイムアウトを設定して、操作の完了を待機する時間を制限する方法を説明します。

理解しておく必要があること

テクノロジ

必要条件

  • 以下の情報は、ネットワーク接続にソケットを使うあらゆる接続型 (ネットワーク認識型) の Windows ランタイム アプリに当てはまります。このトピックは Windows 8.1、Windows Phone 8.1、Windows Server 2012 の JavaScript で記述されたアプリに適用されます。

  • このトピックのコード例は、JavaScript で記述されています。ソケットについての基本的な理解があることが条件となります。

手順

ソケット操作の既定タイムアウトの概要

Windows ランタイム アプリでは StreamSocket クラスが TCP ソケットを実装します。TCP ソケットは、ネットワーク データを送受信する前に、接続を確立する必要があります。基盤となる TCP ソケットの Windows 8.1、Windows Phone 8.1、Windows Server 2012 での実装では、すべての TCP 接続ソケット操作に既定のタイムアウトが設定されます。ホスト名またはエンドポイントが使われる場合、既定のタイムアウトは発信元と宛先のアドレス ペアごとに 3 分 (180 秒) です。つまり、宛先のホスト名が 2 つの IP アドレスを持っている場合、6 分が経過するまで接続操作はタイムアウトにはなりません。この既定のタイムアウトは、Windows ランタイム アプリを使用するカスタマー エクスペリエンスにおいては長すぎる場合があります。StreamSocket クラスを使うアプリでは、ストリーム ソケット接続操作に、より短いカスタム タイムアウトを設定することができます。

DatagramSocket クラスと StreamSocket クラスには、ネットワーク データを送受信する際の既定タイムアウトはありません。そのため、すべての送信操作と受信操作は待機したままの状態になります。ソケットを使う Windows ランタイム アプリでは、カスタマー エクスペリエンスを向上させるためにこれらの操作にタイムアウトを設定することができます。

StreamSocketListener クラスは、着信接続要求をリッスンし、待機したままの状態になります。

ソケット操作にカスタム タイムアウトを設定する方法

JavaScript 言語はタイムアウト イベントをサポートしているので、指定された時間間隔で何らかのコードを実行することができます。

JavaScript のタイミング イベント

  • setInterval() - 指定された時間間隔 (ミリ秒単位) で、関数を繰り返し実行します。
  • setTimeout() - 指定の時間 (ミリ秒単位) 待機した後、関数を 1 回実行します。

タイミング イベント関数は、HTML DOM Window オブジェクトで実装されています。

WinJS 名前空間は、WinJS.Promise オブジェクトを含む、特別な JavaScript 用 Windows ライブラリの機能を提供します。timeout(timeout, promise) メソッドは、setTimeout 関数をラップしています。timeout パラメーターで指定した時間 (ミリ秒単位) 以内に promise が完了しなかった場合、Windows ストア アプリでは timeout(timeout, promise) メソッドを使ってその promise をキャンセルすることができます。 timeout パラメーターで指定された時間内に操作が完了しなかった場合、ソケット操作で timeout(timeout, promise) メソッドを promise パラメーターとして呼び出して操作をタイムアウトすることができます。ソケット操作は、操作が保留中である限りキャンセルすることができます。

WinJS.Promise オブジェクトと timeout(timeout, promise) メソッドは、すべての非同期ソケット操作を含む、Windows ランタイム アプリのあらゆる非同期操作で使用できます。 通常の完了については、timeout(timeout, promise) メソッド呼び出しの後に ".then" を追加します。

3 つのどのクラスでも、タイムアウトを使うための基本的なモデルは同じです。 以下では StreamSocket での接続操作を例に説明しています。ネットワーク データを DatagramSocket オブジェクトまたは StreamSocket オブジェクトで送受信する場合も、着信接続を StreamSocketListener オブジェクトでリッスンする場合も、同じモデルを使ってタイムアウトを実装できます。

  • StreamSocket を作成します。
  • timeout(timeout, promise) メソッドを呼び出します。このとき、StreamSocket.connectAsync メソッドの 1 つを promise パラメーターとして指定します。
  • 正常時およびエラー時の処理を行う .then(successFunction, errorFunction) メソッドを追加したら、ソース コードは完成です。
  • エラー時は、ソケットを閉じます。 StreamSocket 操作の promise がいったんキャンセルされると、キャンセルされた StreamSocket は使用できなくなります。

以下のサンプルは、StreamSocket 接続操作のカスタム タイムアウトを実装しています。


var clientSocket = null;
var timeout = 10000; // 10 seconds
function openClient() {
    var serverHostName = new Windows.Networking.HostName("www.contoso.com");
    var serviceName = "http";
 
    // displayStatus("Client: connection started.");
    clientSocket = new Windows.Networking.Sockets.StreamSocket();
    //var promise = clientSocket.connectAsync(serverHostName, serviceName)
    WinJS.Promise.timeout(timeout, clientSocket.connectAsync(serverHostName, serviceName).then(function () {
        // displayStatus("Client: connection completed.");
        // Do your socket operations here.
 
    }, function (reason) {
        // There are many reasons for this failure: the promise might have 
        // timed out, or the server host refused the connection, or there
        // was an TCP issue, or several other possibilities.
 
        // displayStatus("Client: connection failed. ");
        // displayStatus(reason.message);
        clientSocket.close();
        clientSocket = null;
    }
    ));
}

関連トピック

その他

ソケットを使った接続

データグラム ソケットを使って接続する方法

ストリーム ソケットを使って接続する方法

TLS/SSL を使ってソケット接続のセキュリティを確保する方法

リファレンス

DatagramSocket

StreamSocket

StreamSocketListener

timeout(timeout, promise)

Windows.Networking.Sockets

WinJS

WinJS.Promise

サンプル

promise のサンプル