Поделиться через


Инфраструктура одноранговых событий

Инфраструктура одноранговых узлов использует события для уведомления приложений об изменениях, произошедших в одноранговой сети, например узла, добавляемого или удаленного из графа. Инфраструктуры однорангового графинга и группирования одноранговых узлов используют инфраструктуру событий однорангового узла.

Получение уведомления о событиях однорангового узла

Одноранговый узел может регистрироваться для получения уведомлений при изменении атрибута графа или группы или определенного однорангового события. Одноранговое приложение вызывает функцию 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 при регистрации приложения.

Обработка ссылок на подключение Graph

При вызове 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 ПОДКЛЮЧЕНИЯ, указывающие, что группа имеет по крайней мере одно подключение. Это значение состояния можно получить путем вызова 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;
}