ピア イベント インフラストラクチャ

ピア インフラストラクチャは、イベントを使用して、ピア ネットワーク内で発生した変更 (グラフに追加または削除されたノードなど) をアプリケーションに通知します。 ピア グラフとピア グループ化インフラストラクチャでは、ピア イベント インフラストラクチャが使用されます。

ピア イベント通知の受信

ピアは、グラフまたはグループの属性が変更されたとき、または特定のピア イベントが発生したときに通知を受信するように登録できます。 ピア アプリケーションは、PeerGraphRegisterEvent または PeerGroupRegisterEvent関数呼び出し、イベント ハンドルをピア インフラストラクチャに渡します。これは、以前は CreateEvent呼び出しによって作成されています。 ピア インフラストラクチャは、このハンドルを使用して、ピア イベントが発生したことをアプリケーションに通知します。

アプリケーションは、アプリケーションが通知を要求している特定のピア イベントをピア インフラストラクチャに示す一連の PEER_GRAPH_EVENT_REGISTRATION または PEER_GROUP_EVENT_REGISTRATION 構造体も渡します。 アプリケーションでは、渡される構造体の正確な数も指定する必要があります。

ピア グラフ イベント

ピア グラフ アプリケーションは、9 つのピア グラフ イベントの通知を受信するように登録できます。 各イベント名の前には、PEER_GRAPH_EVENT_(例: PEER_GRAPH_STATUS_CHANGED) が付けられます。 特に明記されていない限り、変更に関する情報は、PeerGraphGetEventDataを使用して取得されます。

  • PEER_GRAPH_EVENT_STATUS_CHANGED は、グラフの状態が変更されたことを示します 。たとえば、ノードがグラフと同期しています。

  • PEER_GRAPH_EVENT_PROPERTY_CHANGED は、グラフまたはグループのプロパティが変更されたことを示します 。たとえば、グラフのフレンドリ名が変更されています。

    注意

    変更された情報を取得するには、アプリケーション PeerGraphGetProperties を呼び出す必要があります。

     

  • PEER_GRAPH_EVENT_RECORD_CHANGED は、レコードが変更されたことを示します (レコードが削除されるなど)。

  • PEER_GRAPH_EVENT_DIRECT_CONNECTION は、直接接続が変更されたことを示します (たとえば、ノードが接続されています)。

  • PEER_GRAPH_EVENT_NEIGHBOR_CONNECTION は、ノードが接続されているなど、近隣ノードへの接続が変更されたことを示します。

  • PEER_GRAPH_EVENT_INCOMING_DATA は、データが直接接続または近隣接続から受信されたことを示します。

  • PEER_GRAPH_EVENT_CONNECTION_REQUIRED は、Graphing インフラストラクチャに新しい接続が必要であることを示します。

    注意

    PeerGraphConnect呼び出すと、新しいノードに接続されます。 PeerGraphGetEventData呼び出しても、データは返されません。

     

  • PEER_GRAPH_EVENT_NODE_CHANGED は、たとえば IP アドレスが変更されたなど、ノードプレゼンス情報が変更されたことを示します。

  • PEER_GRAPH_EVENT_SYNCHRONIZED は、特定のレコードの種類が同期されていることを示します。

アプリケーションは、ピア イベントが発生したことを示す通知を受け取った後、PeerGraphGetEventData呼び出し、PeerGraphRegisterEventによって返されるピア イベント ハンドル渡します。 ピア インフラストラクチャは、要求されたデータを含む PEER_GRAPH_EVENT_DATA 構造体へのポインターを返します。 この関数は、PEER_S_NO_EVENT_DATA が返されるまで呼び出す必要があります。

アプリケーションがピア イベント通知を必要としない場合、アプリケーションは PeerGraphUnregisterEventを呼び出し、アプリケーションの登録時に PeerGraphRegisterEventによって返されるピア イベント ハンドル渡します。

グラフ接続の紹介の処理

PeerGraphConnect呼び出されると、非同期の PEER_GRAPH_EVENT_NEIGHBOR_CONNECTION イベントによって、接続ピアに成功または失敗が通知されます。 特定のネットワークの問題 (正しく構成されていないファイアウォールなど) が原因で接続に失敗した場合、PEER_GRAPH_EVENT_NEIGHBOR_CONNECTION イベントが発生し、接続状態が PEER_CONNECTION_FAILEDに設定されます。

ただし、ピアがビジー 状態のノードに接続しようとしたときに紹介を受け取ると、接続状態が PEER_CONNECTION_FAILEDに設定された接続ピアで PEER_GRAPH_EVENT_NEIGHBOR_CONNECTION が発生します。 接続ピアは、それ自体がビジーであり、紹介を送信する可能性がある別のノードを参照でき、接続ピアで同じイベントと状態が発生します。 PEER_CONNECTION_FAILED イベントの状態をもたらす紹介のこのチェーンは、接続試行の最大数が使い果たされるまで続行できます。 ピアには、完全な接続試行と接続の紹介の違いを判断するメカニズムがありません。

この問題に対処するには、ピア グラフの状態変更イベントを使用して、接続試行が正常に実行されたかどうかを判断することを検討する必要があります。 イベントが特定の時間内に受信されない場合、アプリケーションは、接続ピアが参照されており、ピア アプリケーションが接続試行を失敗と見なす必要があると想定できます。

ピア グループ化イベント

ピア グループ化アプリケーションは、8 つのピア イベントの通知を受信するように登録できます。 各イベント名は、PEER_GROUP_EVENT_で始まる。たとえば、PEER_GROUP_EVENT_STATUS_CHANGEDします。 特に明記されていない限り、変更に関する情報は、PeerGroupGetEventDataを使用して取得されます。

  • PEER_GROUP_EVENT_STATUS_CHANGED は、グループの状態が変更されたことを示します。 可能な状態の値は 2 つあります。PEER_GROUP_STATUS_LISTENINGは、グループに接続がなく、新しいメンバーを待機していることを示します。と PEER_GROUP_STATUS_HAS CONNECTIONS。グループに少なくとも 1 つの接続があることを示します。 この状態の値は、このイベントが発生した後 PeerGroupGetStatus を呼び出すことによって取得できます。
  • PEER_GROUP_EVENT_PROPERTY_CHANGED は、グループのプロパティがグループ作成者によって変更または更新されたことを示します。
  • PEER_GROUP_EVENT_RECORD_CHANGED は、レコード操作が実行されたことを示します。 このイベントは、グループに参加しているピアがレコードを発行、更新、または削除したときに発生します。 たとえば、このイベントは、チャット アプリケーションがチャット メッセージを送信するときに発生します。
  • PEER_GROUP_EVENT_MEMBER_CHANGED は、グループ内のメンバーの状態が変更されたことを示します。 状態の変更は次のとおりです。
    • PEER_MEMBER_CONNECTED. ピアがグループに接続されている。
    • PEER_MEMBER_DISCONNECTED. ピアがグループから切断されました。
    • PEER_MEMBER_JOINED. ピアの新しいメンバーシップ情報が発行されました。
    • PEER_MEMBER_UPDATED. ピアは、新しい IP アドレスなどの新しい情報で更新されました。
  • PEER_GROUP_EVENT_NEIGHBOR_CONNECTION. グループ内の近隣接続に参加するピアは、このイベントに登録する必要があります。 このイベントに登録しても、ピアはデータを受信できません。このイベントの登録では、近隣接続の要求が受信されたときにのみ通知が保証されます。
  • PEER_GROUP_EVENT_DIRECT_CONNECTION. グループ内の直接接続に参加するピアは、このイベントに登録する必要があります。 このイベントに登録しても、ピアはデータを受信できません。このイベントの登録では、直接接続の要求を受信した場合にのみ通知が保証されます。
  • PEER_GROUP_EVENT_INCOMING_DATA. 近隣または直接接続経由でデータを受信するピアは、このイベントに登録する必要があります。 このイベントが発生すると、他の参加ピアによって送信される不透明なデータは、PeerGroupGetEventData呼び出すことによって取得できます。 このイベントを受信するには、ピアが以前に PEER_GROUP_EVENT_DIRECT_CONNECTION または PEER_GROUP_EVENT_NEIGHBOR_CONNECTIONに登録されている必要があります。
  • PEER_GROUP_EVENT_CONNECTION_FAILED. 何らかの理由で接続に失敗しました。 このイベントが発生してもデータは提供されず、PeerGroupGetEventData呼び出さないでください。

アプリケーションは、ピア イベントが発生したことを示す通知 (PEER_GROUP_EVENT_CONNECTION_FAILEDを除く) を受け取った後、PeerGroupGetEventData呼び出し、PeerGroupRegisterEventによって返されたピア イベント ハンドル渡します。 ピア インフラストラクチャは、要求されたデータを含む PEER_GROUP_EVENT_DATA 構造体へのポインターを返します。 この関数は、PEER_S_NO_EVENT_DATA が返されるまで呼び出す必要があります。 アプリケーションでピア イベントの通知が不要になった場合は、PeerGroupUnregisterEventする呼び出しを行い、PeerGroupRegisterEvent によって返されたピア イベント ハンドルを渡 必要があります。

ピア グラフ イベントの登録の例

次のコード サンプルは、ピア グラフ イベントに登録する方法を示しています。

//-----------------------------------------------------------------------------
// Function: RegisterForEvents
//
// Purpose:  Registers the EventCallback function so it can be called for only
//           the events that are specified.
//
// Returns:  HRESULT
//
HRESULT RegisterForEvents()
{
    HPEEREVENT  g_hPeerEvent = NULL;        // The one PeerEvent handle
    HANDLE      g_hEvent = NULL;            // Handle signaled by Graphing when we have an event
    HRESULT hr = S_OK;
    PEER_GRAPH_EVENT_REGISTRATION regs[] = {
        { PEER_GRAPH_EVENT_RECORD_CHANGED, 0 },
        { PEER_GRAPH_EVENT_NODE_CHANGED,   0 },
        { PEER_GRAPH_EVENT_STATUS_CHANGED, 0 },
        { PEER_GRAPH_EVENT_DIRECT_CONNECTION, 0 },
        { PEER_GRAPH_EVENT_INCOMING_DATA, 0 },
    };

    g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (g_hEvent == NULL)
    {
        wprintf(L"CreateEvent call failed.\n");
        hr = E_OUTOFMEMORY;
    }
    else
    {
        hr = PeerGraphRegisterEvent(g_hGraph, g_hEvent, celems(regs), regs,  &g_hPeerEvent);
        if (FAILED(hr))
        {
           wprintf(L"PeerGraphRegisterEvent call failed.\n");
            CloseHandle(g_hEvent);
            g_hEvent = NULL;
        }
    }

    if (SUCCEEDED(hr))
    {
        if (!RegisterWaitForSingleObject(&g_hWait, g_hEvent, EventCallback, NULL, INFINITE, WT_EXECUTEDEFAULT))
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
            wprintf(L"Could not set up event callback.\n");
            CloseHandle(g_hEvent);
            g_hEvent = NULL;
        }
    }

    return hr;
}