Using namedPipes, how to cover many events?

To cover many events in a Named Pipes communication system between a client and server, you need to define a message protocol that includes a way to differentiate between the various types of requests (or events) that can be sent over the pipe. In the case of a large number of events, you can design a protocol that uses event IDs or command codes to represent different actions. This allows the server and client to process the messages appropriately based on the event.

Strategy for Handling Multiple Events with Named Pipes

  1. Message Format with Event ID:

    • Each message contains an event ID (or command ID) that specifies what kind of event is being triggered (e.g., login, get data, send message, etc.).
    • The payload contains the actual data needed for that event (e.g., username, session ID, message text, etc.).
  2. Server-Side Event Handling:

    • The server processes the message, extracts the event ID, and routes the request to the appropriate handler function based on the event.
  3. Client-Side Event Triggering:

    • The client formats messages to include the correct event ID and payload before sending them to the server.

Message Structure

You can define a structure like this:

 

plaintext

[Event ID][Payload]
  • Event ID: A unique identifier for the API (event) being called, like 0x01 for login, 0x02 for fetching data, etc.
  • Payload: The data associated with the event. The format of the payload can vary depending on the event.

Example of Multiple Events with Named Pipes

Let’s implement a basic example where the server can handle multiple events such as:

  1. Login (Event ID: 0x01)
  2. Get Data (Event ID: 0x02)
  3. Send Message (Event ID: 0x03)
Step-by-Step Implementation

1. Server Implementation

The server listens for messages from the client, reads the event ID, and dispatches the request to the appropriate handler.

 

cpp

#include <windows.h>
#include <iostream>
#include <string>

// Function prototypes
void handleLogin(const std::string& payload);
void handleGetData(const std::string& payload);
void handleSendMessage(const std::string& payload);

// Helper function to send a response back to the client
void sendResponse(HANDLE hPipe, const std::string& response, OVERLAPPED& olWrite) {
    DWORD bytesWritten;
    BOOL result = WriteFile(hPipe, response.c_str(), response.size(), &bytesWritten, &olWrite);
    if (!result && GetLastError() != ERROR_IO_PENDING) {
        std::cerr << "Failed to write to the pipe. Error: " << GetLastError() << std::endl;
    }
    WaitForSingleObject(olWrite.hEvent, INFINITE);
    GetOverlappedResult(hPipe, &olWrite, &bytesWritten, FALSE);
}

int main() {
    const wchar_t* pipeName = L"\\\\.\\pipe\\MyEventPipe";

    HANDLE hPipe = CreateNamedPipe(
        pipeName,
        PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // Overlapped mode for async
        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
        1, // Only one instance
        1024, // Output buffer size
        1024, // Input buffer size
        0, // Default timeout
        NULL // Default security attributes
    );

    if (hPipe == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to create named pipe. Error: " << GetLastError() << std::endl;
        return 1;
    }

    std::cout << "Waiting for a client to connect..." << std::endl;

    OVERLAPPED olConnect = {};
    olConnect.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    BOOL isConnected = ConnectNamedPipe(hPipe, &olConnect);
    if (!isConnected && GetLastError() != ERROR_IO_PENDING) {
        std::cerr << "Failed to connect to the client. Error: " << GetLastError() << std::endl;
        CloseHandle(hPipe);
        return 1;
    }

    WaitForSingleObject(olConnect.hEvent, INFINITE);
    std::cout << "Client connected!" << std::endl;

    char buffer[128];
    DWORD bytesRead, bytesWritten;
    OVERLAPPED olRead = {};
    OVERLAPPED olWrite = {};

    olRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    olWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    // Server main loop
    while (true) {
        BOOL result = ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, &olRead);
        if (!result && GetLastError() != ERROR_IO_PENDING) {
            std::cerr << "Failed to read from the pipe. Error: " << GetLastError() << std::endl;
            break;
        }

        WaitForSingleObject(olRead.hEvent, INFINITE);
        GetOverlappedResult(hPipe, &olRead, &bytesRead, FALSE);
        buffer[bytesRead] = '\0'; // Null-terminate the string

        // Process event ID
        int eventID = buffer[0];  // Assuming first byte is the event ID
        std::string payload = std::string(buffer + 1, bytesRead - 1); // Remaining data is payload

        switch (eventID) {
            case 0x01:
                handleLogin(payload);
                sendResponse(hPipe, "Login Successful", olWrite);
                break;
            case 0x02:
                handleGetData(payload);
                sendResponse(hPipe, "Data Retrieved", olWrite);
                break;
            case 0x03:
                handleSendMessage(payload);
                sendResponse(hPipe, "Message Sent", olWrite);
                break;
            default:
                std::cerr << "Unknown Event ID received!" << std::endl;
                sendResponse(hPipe, "Unknown Event", olWrite);
                break;
        }

        if (payload == "exit") break;  // Exit if 'exit' command is sent
    }

    CloseHandle(olConnect.hEvent);
    CloseHandle(olRead.hEvent);
    CloseHandle(olWrite.hEvent);
    CloseHandle(hPipe);
    std::cout << "Server exiting..." << std::endl;
    return 0;
}

// Event handlers
void handleLogin(const std::string& payload) {
    std::cout << "Handling Login Event. Payload: " << payload << std::endl;
}

void handleGetData(const std::string& payload) {
    std::cout << "Handling GetData Event. Payload: " << payload << std::endl;
}

void handleSendMessage(const std::string& payload) {
    std::cout << "Handling SendMessage Event. Payload: " << payload << std::endl;
}

cpp

2. Client Implementation

The client sends different events to the server by setting the event ID and the corresponding payload.

 

cpp

#include <windows.h>
#include <iostream>
#include <string>

void sendRequest(HANDLE hPipe, int eventID, const std::string& payload, OVERLAPPED& olWrite) {
    std::string message;
    message.push_back(eventID);  // Add Event ID as the first byte
    message += payload;          // Append the payload

    DWORD bytesWritten;
    BOOL result = WriteFile(hPipe, message.c_str(), message.size(), &bytesWritten, &olWrite);
    if (!result && GetLastError() != ERROR_IO_PENDING) {
        std::cerr << "Failed to write to the pipe. Error: " << GetLastError() << std::endl;
    }
    WaitForSingleObject(olWrite.hEvent, INFINITE);
    GetOverlappedResult(hPipe, &olWrite, &bytesWritten, FALSE);
}

std::string receiveResponse(HANDLE hPipe, OVERLAPPED& olRead) {
    char buffer[128];
    DWORD bytesRead;

    BOOL result = ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, &olRead);
    if (!result && GetLastError() != ERROR_IO_PENDING) {
        std::cerr << "Failed to read from the pipe. Error: " << GetLastError() << std::endl;
        return "";
    }

    WaitForSingleObject(olRead.hEvent, INFINITE);
    GetOverlappedResult(hPipe, &olRead, &bytesRead, FALSE);

    buffer[bytesRead] = '\0'; // Null-terminate the string
    return std::string(buffer);
}

int main() {
    const wchar_t* pipeName = L"\\\\.\\pipe\\MyEventPipe";

    std::cout << "Attempting to connect to the server..." << std::endl;
    HANDLE hPipe = CreateFile(
        pipeName,
        GENERIC_READ | GENERIC_WRITE,
        0,                           // No sharing
        NULL,                        // Default security attributes
        OPEN_EXISTING,               // Opens existing pipe
        FILE_FLAG_OVERLAPPED,        // Overlapped mode for async
        NULL                         // No template file
    );

    if (hPipe == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to connect to the server. Error: " << GetLastError() << std::endl;
        return 1;
    }

    std::cout << "Connected to the server!" << std::endl;

    OVERLAPPED olWrite

cpp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值