pipe道通信C ++

我正在编写两个必须通信的litle c ++应用程序。 第一个将是一个服务,每隔一段时间,必须提醒用户的东西。 由于服务不能创build窗口,我devise的应用程序是两个单独的可执行文件。

该服务将使用通知程序进行通信。

该服务只需要发送文本消息到通知器将在系统托盘上显示一个气球。

我正尝试使用命名pipe道,我想我几乎在那里,但不是那里。 我到目前为止是:

在通知方:

m_hInPipe = CreateNamedPipe(L"\\\\.\\pipe\\nhsupspipe", PIPE_ACCESS_INBOUND, PIPE_WAIT, 1, 1024, 1024, 60, NULL); 

含义我创build了一个名为nhsupspipe的pipe道,一个入站pipe道。

在服务方面:

 if (!WriteFile(m_hOutPipe, "My message to the user?", 23, &escritos, &o)) std::cout << "ERROR: " << GetLastError(); 

debugging我可以看到一切正常,pipe道被创build,WriteFile将23个字节写入pipe道。

我的问题是:如何,在通知方我将能够读取这些字节? 有没有消息发送到过程? 我必须为pipe道编写一个处理程序吗? 什么?

Solutions Collecting From Web of "pipe道通信C ++"

从客户端(你的服务)和服务器(通知器)的一些简单的片段[ 注意:这是从我刚才做的一个项目改编而来,反过来受到来自CreateNamedPipe&co的MSDN示例的严重影响 ] :

服务器端:

 HANDLE hPipe = INVALID_HANDLE_VALUE; bool bConnected = false; hPipe = CreateNamedPipe( L"\\\\.\\pipe\\nhsupspipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, sizeof( Message ), 0, 0, NULL ); // failed to create pipe? if( hPipe == INVALID_HANDLE_VALUE ){ return -1; } // Wait for the client to connect; if it succeeds, // the function returns a nonzero value. If the function // returns zero, GetLastError returns ERROR_PIPE_CONNECTED. bConnected = ConnectNamedPipe( hPipe, NULL ) ? true : ( GetLastError() == ERROR_PIPE_CONNECTED ); if( bConnected ){ while( true ){ unsigned long ulBytesRead = 0; // read client requests from the pipe. bool bReadOk = ReadFile( hPipe, &message, sizeof( message ), &ulBytesRead, NULL ); // bail if read failed [error or client closed connection] if( !bReadOk || ulBytesRead == 0 ) break; // all ok, process the message received } } else{ // the client could not connect, so close the pipe. CloseHandle( hPipe ); } return 0; 

客户端:

 HANDLE hPipe = INVALID_HANDLE_VALUE; // create the named pipe handle hPipe = CreateFile( L"\\\\.\\pipe\\nhsupspipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); // if everything ok set mode to message mode if( INVALID_HANDLE_VALUE != hPipe ){ DWORD dwMode = PIPE_READMODE_MESSAGE; // if this fails bail out if( !SetNamedPipeHandleState( hPipe, &dwMode, NULL, NULL ) ){ CloseHandle( hPipe ); return -1; } } unsigned long ulBytesWritten = 0; bool bWriteOk = WriteFile( hPipe, ( LPCVOID )&message, sizeof( Message ), &ulBytesWritten, NULL ); // check if the writing was ok if( !bWriteOk || ulBytesWritten < sizeof( Message ) ){ return -1; } // written ok return 0; 

上面提到的消息是一个结构,这将是你的消息,你可能会打包 。

因为在你的场景中,客户端(服务)可能会在服务器(通知程序)之前运行,你需要在客户端有一些重新连接策略。

稍微不同的是,你应该仔细考虑奥斯特曼先生在回答中所说的话(即使是因为他是拉里·奥斯特曼也不例外)。

通常在线程或消息循环中,您需要在通知方使用ReadFile或ReadFileEx (用于重叠的I / O)。 另请参阅CreateNamedPipe和WaitNamedPipe的文档。

在这种情况下,我可能会使用RPC而不是原始的命名管道。 使用原始的命名管道,你必须解析来自客户端的数据,这引入了安全错误的可能性。 使用RPC,您可以让RPC为您解析数据,从而降低引入错误的几率。

不完全是问题,但另一个选项是CreateEvent()和一个内存映射文件。

如果我这样做,我会让服务端执行CreateNamedPipe (出站),然后调用ConnectNamedPipe等待通知程序连接。

在通知方,我会使用FILE_FLAG_OVERLAPPED CreateFile 。 这样,当数据可以读取时,管道的句柄将被发信号通知。 您的通知程序(可能)也会维护一个GUI,因此您可能希望在其事件循环中调用MsgWaitForMultipleObjects 。 这将等待处理消息或者处理管道上的数据。 除了返回值与GetMessage()略有不同之外,它几乎像普通的事件循环一样工作 – 如果您的句柄被发信号,它将返回WAIT_OBJECT_0如果您有消息,则返回WAIT_OBJECT_0 + 1 (假设您只有它等待一个句柄 – 这真的是WAIT_OBJECT_0 + N ,其中N是你等待的句柄的数量)。 在大多数情况下,它就像一个正常的PeekMessageGetMessage循环 – 等待有些事情要做,然后再等待。