一个客户一次收到Windows事件

Windows events are received by one client at a time

本文关键字:Windows 事件 客户 一个 一次      更新时间:2023-10-16

我有一个小程序(server.exe)每秒发送一个Windows事件,而另一个程序(client.exe)等待此事件。

如果我只有一个客户端,则可以正常工作,但是当我启动多个客户端时,其中只有一个会收到下一个事件。我需要所有客户都会通知每个事件。我不知道如何修复我的程序。

服务器发送事件如下:

auto handle = CreateEvent(nullptr, FALSE, FALSE, "SERVER_HEARTBEAT");
SetEvent(handle)

客户端接收到下面的事件

static HANDLE handles[1];
handles[0] = CreateEvent(nullptr, FALSE, FALSE, "SERVER_HEARTBEAT");
auto bit_no = WaitForMultipleObjectsEx(1, 
                      static_cast<CONST HANDLE *>(handles),    
                      TRUE,                                 
                      INFINITE,                                    
                      TRUE);  

我有一个批处理文件可以启动4个客户端和1个服务器:

start "cmd /c "start "client.exe" 0
start "cmd /c "start "client.exe" 1
start "cmd /c "start "client.exe" 2
start "cmd /c "start "client.exe" 3
start "cmd /c "start "server.exe"

输出显示在客户端之间分布的事件显然是随机的:

SERVER> Sending the event each second...
CLIENT 3>  received heartbeat
CLIENT 1>  received heartbeat
CLIENT 2>  received heartbeat
  ...

server.exe的完整代码(建立在Visual Studio 2015)

#include <windows.h>
#include <iostream>
int main(int argc, char* argv[])
{
    std::cout << "SERVER> Sending the event each second..." << std::endl;
    std::string  line;
    auto handle = CreateEvent(nullptr, FALSE, FALSE, "SERVER_HEARTBEAT");
    if (handle == nullptr)
    {
        std::cout << "error: create event failed" << std::endl;
        exit(0);
    }
    while (true)
    {
        if (!SetEvent(handle))
        {
            std::cout << "error: SetEvent failed" << std::endl;
        }
        Sleep(1000);
    }
    CloseHandle(handle);
    return 0;
}

client.exe的完整代码(建立在Visual Studio 2015)

#include <windows.h>
#include <string>
#include <iostream>
#include <locale>
int main(int argc, char* argv[])
{
    // Set the client id
    if (argc != 2)
    {
        std::cout << "error: missing client id" << std::endl;
        exit(0);
    }
    // Validate the client id to a be positive value
    std::string input = argv[1];
    std::locale loc;
    auto it = begin(input);
    while (it != end(input) && std::isdigit(*it, loc)) ++it;
    if (it != end(input))
    {
        std::cout << "invalid client id specified: " << input.c_str() << std::endl;
        return 1;
    }
    auto client_id = std::stoi(input);
    if (client_id < 0)
    {
        std::cout << "the client id must be a positive number: " << input.c_str() << std::endl;
        return 1;
    }
    // Initialize the client to listen the heartbeat from the DCS App Manager running on the same station
    static HANDLE handles[1];
    handles[0] = CreateEvent(nullptr, FALSE, FALSE, "SERVER_HEARTBEAT");
    if (handles[0] == nullptr)
    {
        std::cout << "error: create event failed" << std::endl;
        exit(0);
    }
    while (true)
    {
        auto bit_no = WaitForMultipleObjectsEx(
            1,                                    // number of handles in the handle array 
            static_cast<CONST HANDLE *>(handles), // pointer to the object-handle array    
            TRUE,                                 // returns when the state of any one of 
                                                  // the objects set to is signaled        
            INFINITE,                             // time-out interval never elapses       
            TRUE);                                // Alertable
        if (bit_no == WAIT_FAILED)
        {
            std::cout << "error: WaitForMultipleObjects failed" << std::endl;
            break;
        }
        std::cout << "CLIENT " << client_id << ">  received heartbeat" << std::endl;
    }
    CloseHandle(handles[0]);
    return 0;
}

在最终解决方案下方,基于 Harry Johnston 的评论,他被告知创建与最大数量的客户数量一样数量。结果,所有客户端都会定期收到服务器心跳消息。

server.exe的完整代码

#include <windows.h>
#include <iostream>
#include <string>
#define MAX_CLIENTS 20
int main(int argc, char* argv[])
{
    std::cout << "SERVER> Sending the event each second..." << std::endl;
    std::string  line;
    static HANDLE handles[MAX_CLIENTS];
    for (auto client_id = 0; client_id < MAX_CLIENTS; client_id++)
    {
        auto eventName = std::string("SERVER_HEARTBEAT_") + std::to_string(client_id);
        std::cout << "create event " << eventName << std::endl;
        handles[client_id] = CreateEvent(nullptr, FALSE, FALSE, eventName.c_str());
        if (handles[client_id] == nullptr)
        {
            std::cout << "error: create event failed" << std::endl;
            exit(0);
        }
    }
    while (true)
    {
        std::cout << "sending events" << std::endl;
        for (auto client_id = 0; client_id < MAX_CLIENTS; client_id++)
        {
            if (!SetEvent(handles[client_id]))
            {
                std::cout << "error: SetEvent failed" << std::endl;
            }
        }
        Sleep(1000);
    }
    for (auto client_id = 0; client_id < MAX_CLIENTS; client_id++)
    {
        CloseHandle(handles[client_id]);
    }
    return 0;
}

client.exe

的完整代码
#include <windows.h>
#include <string>
#include <iostream>
#include <locale>
int main(int argc, char* argv[])
{
    // Set the client id
    if (argc != 2)
    {
        std::cout << "error: missing client id" << std::endl;
        exit(0);
    }
    // Validate the client id to a be positive value
    std::string input = argv[1];
    std::locale loc;
    auto it = begin(input);
    while (it != end(input) && std::isdigit(*it, loc)) ++it;
    if (it != end(input))
    {
        std::cout << "invalid client id specified: " << input.c_str() << std::endl;
        return 1;
    }
    auto client_id = std::stoi(input);
    if (client_id < 0)
    {
        std::cout << "the client id must be a positive number: " << input.c_str() << std::endl;
        return 1;
    }
    // Initialize the client to listen the heartbeat from the DCS App Manager 
    // running on the same station
    static HANDLE handles[1];
    auto eventName = std::string("SERVER_HEARTBEAT_") + std::to_string(client_id);
    std::cout << "listening for the event " << eventName << std::endl;
    handles[0] = CreateEvent(nullptr, FALSE, FALSE, eventName.c_str());
    if (handles[0] == nullptr)
    {
        std::cout << "error: create event failed" << std::endl;
        exit(0);
    }
    while (true)
    {
        auto result = WaitForMultipleObjectsEx(
            1,                                    // number of handles in the handle array 
            static_cast<CONST HANDLE *>(handles), // pointer to the object-handle array    
            TRUE,                                 // returns when the state of any one of 
                                                  // the objects set to is signaled        
            INFINITE,                             // time-out interval never elapses       
            TRUE);                                // Alertable
        if (result == WAIT_FAILED)
        {
            std::cout << "error: WaitForMultipleObjects failed" << std::endl;
            break;
        }
        std::cout << "CLIENT " << client_id << ">  received heartbeat" << std::endl;
    }
    CloseHandle(handles[0]);
    return 0;
}