使用 Boost.Asio 的 C++ 命名管道服务器

问题描述 投票:0回答:1

我一直直接使用Windows API来创建命名管道服务器,如下所示:

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

int main() {
    // Define the name of the named pipe
    const wchar_t* pipeName = L"\\\\.\\pipe\\MyNamedPipe";

    // Create the named pipe
    HANDLE hPipe = CreateNamedPipe(
        pipeName,                  // Pipe name
        PIPE_ACCESS_DUPLEX,        // Pipe open mode
        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, // Pipe mode
        PIPE_UNLIMITED_INSTANCES,  // Number of instances
        512,                       // Output buffer size
        512,                       // Input buffer size
        NMPWAIT_USE_DEFAULT_WAIT,  // Timeout for client connection
        nullptr                    // Security attributes
    );

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

    // Wait for a client to connect
    if (ConnectNamedPipe(hPipe, nullptr)) {
        std::cout << "Client connected. Waiting for data...\n";

        // Read data from the client
        char buffer[512];
        DWORD bytesRead;
        if (ReadFile(hPipe, buffer, sizeof(buffer), &bytesRead, nullptr)) {
            std::cout << "Received data from client: " << buffer << std::endl;
        } else {
            std::cerr << "Error reading from pipe. Error code: " << GetLastError() << std::endl;
        }

        // Disconnect the pipe
        DisconnectNamedPipe(hPipe);
    } else {
        std::cerr << "Error waiting for client connection. Error code: " << GetLastError() << std::endl;
    }

    // Close the pipe handle
    CloseHandle(hPipe);

    return 0;
}

此代码可以工作,但最好使用

Boost.Asio
或类似的现代 C++ 解决方案。我在网上找到的所有代码要么不涵盖这个用例,要么无法编译:

#include <iostream>
#include <boost/asio.hpp>

using namespace boost::asio;

int main() {
    io_service ioService;

    // Define the name of the named pipe
    const char* pipeName = "\\\\.\\pipe\\MyNamedPipe";

    // Create a local endpoint
    local::stream_protocol::endpoint endpoint(pipeName);

    // Create and open the acceptor
    local::stream_protocol::acceptor acceptor(ioService, endpoint);

    std::cout << "Waiting for client connection...\n";

    // Wait for a client to connect
    local::stream_protocol::socket socket(ioService);
    acceptor.accept(socket);

    std::cout << "Client connected. Waiting for data...\n";

    // Read data from the client
    char buffer[512];
    size_t bytesRead = socket.read_some(buffer, ioService); // Error 'boost::asio::basic_stream_socket<boost::asio::local::stream_protocol,boost::asio::any_io_executor>::read_some': no matching overloaded function found

    std::cout << "Received data from client: " << std::string(buffer, bytesRead) << std::endl;

    // Close the socket (automatically disconnects the client)
    socket.close();

    return 0;
}

我的 Boost 是通过

vcpkg
安装的版本 1.82.0#1。非常感谢任何帮助 Boost 示例成功编译和运行的帮助。

c++ windows boost-asio named-pipes
1个回答
0
投票

正如我所评论的,

local::stream_protocol
适用于 UNIX 域套接字。它们是 POSIX 特定的。

相反,您想使用 Windows 面向流的句柄

之后,

read_some
函数被记录,并具有以下重载:

template<typename MutableBufferSequence>
    size_t read_some(const MutableBufferSequence & buffers);
template<typename MutableBufferSequence>
    size_t read_some(const MutableBufferSequence & buffers, error_code & ec);

首先,原始字符数组不是缓冲区序列,我完全不清楚为什么要将服务填充到最后一个参数中。

这里已修复:

char buffer[512];
size_t bytesRead = socket.read_some(asio::buffer(buffer));

事实上,我会避免使用 C 风格的原始数组:

std::array<char, 512> buffer;
size_t bytesRead = socket.read_some(asio::buffer(buffer));

松散笔记:

  • 不要乱“使用命名空间”。这是一个坏主意。特别是因为您定义的符号与
    boost::asio
    中声明的符号相冲突(也明确允许 ADL)。
  • 不要使用已弃用的
    io_service
    ,而是使用较新的
    io_context
  • 据我所知,接受不是命名管道的事情(管道是双向流)
© www.soinside.com 2019 - 2024. All rights reserved.