0

我有一个日志记录工具(SS_Log 的后代),它由一个独立的日志查看器和一个 C++ 库组成,用于通过命名管道发送消息。

当记录第一条消息时,客户端通过 C++ lib 启动日志查看器,并执行

HANDLE hPipe = CreateNamedPipe( szPipeName,
                                PIPE_ACCESS_DUPLEX, 
                                PIPE_TYPE_MESSAGE|PIPE_WAIT|PIPE_READMODE_MESSAGE, 
                                PIPE_UNLIMITED_INSTANCES, 
                                SSLOG_MAX_MESSAGE_LENGTH,
                                0, 5000, &sa );

pView->Pipe(hPipe);

if( pView->Pipe() == INVALID_HANDLE_VALUE )
{
    pView->MessageBox( _T("Could not create the pipe for incoming messages.  No messages can be received.   "), 
        _T("Fatal Error"), MB_OK|MB_ICONSTOP );
    return FALSE;
}

// now we loop forever, waiting for messages.  As they come in, send them
// to the SS_Log_WindowView::EraseLog() and SS_Log_WindowView::WriteLog()
// functions as appropriate.
while( TRUE )
{
    ConnectNamedPipe( pView->Pipe(), NULL );
    ...
}

当客户端想要发送消息时,它确实

BOOL bResult = WaitNamedPipe(WindowPipeName(), 20000);
            bResult = CallNamedPipe(WindowPipeName(), (LPVOID)szFinalBuffer, 
                             _tcslen(szFinalBuffer)+1, (LPVOID)NULL, 
                             0, &dwBytesRead, 
                             5000);

我想获得一个与这个命名管道相对应的 HANDLE。文档建议我可以使用CreateFile( WindowPipeName(), GENERIC_READ|GENERIC_WRITE,...OPEN_EXISTING,...). 当我这样做时,某些东西显然开始阻塞,并且日志查看器不再收到任何消息。甚至没有对那个 HANDLE 做任何事情。

是否可以做我想做的事,如果可以,怎么做?

4

1 回答 1

1

日志查看器的循环从调用 开始ConnectNamedPipe。所以它等待客户端连接,读取消息,返回循环顶部并等待客户端再次连接。

这适用,CallNamedPipe因为该功能每次发送消息时都会连接和断开连接。

但是,如果客户端通过打开管道的句柄来创建持久连接,CreateFile那么它只会连接一次。在服务器中,第二个调用ConnectNamedPipe将挂起,等待另一个客户端连接。

如果您希望日志查看器仅处理具有持久连接的单个客户端,则可以有一个循环调用,ConnectNamedPipe然后是一个内部循环,该循环处理来自客户端的消息,直到管道关闭。

如果您想处理多个客户端,那么您当前的解决方案比尝试处理多个同时连接要简单得多。

于 2013-03-20T17:23:05.107 回答