C++ 使用命名管道

Posted

技术标签:

【中文标题】C++ 使用命名管道【英文标题】:C++ Using windows named pipes 【发布时间】:2009-08-06 00:48:23 【问题描述】:

由于某种原因,桅杆和从站都失败了,但是我可以找到任何关于它们如何工作的好例子,所以我不确定我哪里出错了。

主机在 ConnectNamedPipe 之后永远不会退出 WaitForSingleObject,从机在第一次 boost::asio::read 调用中抛出异常,“等待进程打开管道的另一端”,我认为 WaitNamedPipe是打算在 master 中与 ConnectNamedPipe 一起等待吗?

master.cpp

asio::io_service ioservice; 
asio::windows::stream_handle in(ioservice); 
int main()

    HANDLE pipe = INVALID_HANDLE_VALUE;
    try
    
        //create pipe
        pipe = CreateNamedPipe("\\\\.\\pipe\\FLTest",
            PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
            255, 50000,50000, 0, 0);
        if(pipe == INVALID_HANDLE_VALUE)
        
            printWinError();
            return -1;
        
        in.assign(pipe); 
        std::cout << "Created pipe" << std::endl;
        //spawn child
        STARTUPINFO         startInfo;
        ZeroMemory(&startInfo, sizeof(STARTUPINFO));
        startInfo.cb = sizeof(STARTUPINFO);
        PROCESS_INFORMATION procInfo;
        ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION));
        if(CreateProcess(0, "slave.exe", 0,0, FALSE, CREATE_NEW_CONSOLE,
            0, 0, &startInfo, &procInfo))
        
            std::cout << "Slave process created" << std::endl;
        
        else
        
            printWinError();
            DisconnectNamedPipe(pipe);
            return -1;
        

        OVERLAPPED overlapped = 0;
        overlapped.hEvent = CreateEvent(0,TRUE,FALSE,0);
        if(ConnectNamedPipe(pipe, &overlapped) == FALSE)
        
            unsigned error = GetLastError();
            if(error != ERROR_PIPE_CONNECTED &&
                error != ERROR_IO_PENDING)
            
                printWinError();
                DisconnectNamedPipe(pipe);
                return -1;
            
        
        WaitForSingleObject(overlapped.hEvent, INFINITE);
        CloseHandle(overlapped.hEvent);
        std::cout << "Pipe connected" << std::endl;

        for(int i = 0; i < 100; ++i)
        
            boost::system::error_code error;
            unsigned n = i * 5;
            asio::write(in,asio::buffer((char*)&n, sizeof(unsigned)),
                asio::transfer_all(), error);
            if(error)throw boost::system::system_error(error);
        
        std::cout << "Sent data" << std::endl;

        FlushFileBuffers(pipe);
        DisconnectNamedPipe(pipe);
        system("pause");
        return 0;
    
    catch(const std::exception &e)
    
        std::cout << e.what() << std::endl;
        if(pipe != INVALID_HANDLE_VALUE)
            DisconnectNamedPipe(pipe);
        system("pause");
        return -1;
    

slave.cpp

asio::io_service ioservice; 
asio::windows::stream_handle in(ioservice); 
int main()

    try
    
        WaitNamedPipe("\\\\.\\pipe\\FLTest", NMPWAIT_WAIT_FOREVER);

        std::cout << "Pipe avaible" << std::endl;
        HANDLE pipe = CreateNamedPipe("\\\\.\\pipe\\FLTest",
            PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
            255, 50000,50000,0,0);
        if(pipe == INVALID_HANDLE_VALUE)
        
            printWinError();
            return -1;
        

        in.assign(pipe); 
        std::cout << "Pipe connected" << std::endl;

        for(int i = 0; i < 100; ++i)
        
            std::cout << "i: " << i << std::endl;
            boost::system::error_code error;
            unsigned n;
            asio::read(in,asio::buffer((char*)&n,sizeof(unsigned)),
                asio::transfer_all(), error);
            if(error)throw boost::system::system_error(error);
        
        system("pause");
        return 0;
    
    catch(const std::exception &e)
    
        std::cout << e.what() << std::endl;
        system("pause");
        return -1;
    

很明显我搞错了,但是我在网上找不到任何东西可以用来比较我的代码。

【问题讨论】:

【参考方案1】:

在您的从属服务器中,您需要调用 CreateFile() 来打开管道,而不是 CreateNamedPipe。

   HANDLE pipe = CreateFile("\\\\.\\pipe\\FLTest",                 
      GENERIC_READ | GENERIC_WRITE,            
      0,                                          
      NULL,                                       
      OPEN_EXISTING,                              
      FILE_FLAG_OVERLAPPED,                     
      NULL
      );    

【讨论】:

【参考方案2】:

需要在服务器部分指定管道的模式为PIPE_WAIT

【讨论】:

以上是关于C++ 使用命名管道的主要内容,如果未能解决你的问题,请参考以下文章

C++ 使用命名管道

为 Intranet 主机创建 C++ 命名管道

c++ 和 php 中的命名管道

c# c++通信--命名管道通信

使用命名管道的两种 C++ 到 C# 通信

命名管道:C# 服务器、C++ 客户端