對等事件基礎結構
對等基礎結構會使用事件來通知應用程式對等網路內發生的變更,例如,新增或移除圖表中的節點。 對等圖形和對等群組基礎結構會使用對等事件基礎結構。
接收對等事件通知
當圖形或群組的屬性變更或發生特定對等事件時,對等可以註冊以接收通知。 對等應用程式會呼叫 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 表示圖形基礎結構需要新的連線。
注意
對 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_GRAPH_EVENT_NEIGHBOR_CONNECTION ,並將線上狀態設定為 PEER_CONNECTION_FAILED。 連線對等可能會參考另一個本身忙碌且可能會傳送轉介的節點,而且連線對等上會引發相同的事件和狀態。 導致 PEER_CONNECTION_FAILED 事件狀態的這個轉介鏈結可以繼續,直到連線嘗試數目上限已耗盡為止。 對等沒有機制可判斷完整連線嘗試與連線轉介之間的差異。
若要解決此問題,開發人員應考慮使用對等圖形狀態變更事件來判斷連線嘗試是否成功。 如果事件未在特定時間內收到,應用程式可以假設正在參考連線對等,而且對等應用程式應該考慮連線嘗試失敗。
對等群組事件
對等群組應用程式可以註冊以接收 8 個對等事件的通知。 每個事件名稱前面都會加上 PEER_GROUP_EVENT_;例如, PEER_GROUP_EVENT_STATUS_CHANGED。 除非另有說明,否則會使用 PeerGroupGetEventData擷取變更的相關資訊。
- PEER_GROUP_EVENT_STATUS_CHANGED 表示群組狀態已變更。 有兩個可能的狀態值: PEER_GROUP_STATUS_LISTENING,這表示群組沒有連線,而且正在等候新的成員;和 PEER_GROUP_STATUS_HAS CONNECTIONS,表示群組至少有一個連線。 引發此事件之後,可以呼叫 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註冊特定事件時 由 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;
}