对等事件基础结构
对等基础结构使用事件通知应用程序在对等网络中发生的更改,例如,在图形中添加或删除的节点。 对等图和对等分组基础结构使用对等事件基础结构。
接收对等事件通知
当图形或组的属性发生更改或发生特定对等事件时,对等方可以注册以接收通知。 对等应用程序调用 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 返回的对等 事件句柄。
注册对等图形事件的示例
以下代码示例演示如何注册对等图形事件。
//-----------------------------------------------------------------------------
// 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;
}