2013-03-20 4 views
0

У меня есть средство ведения журнала (descendent of SS_Log), которое состоит из независимого средства просмотра журнала и библиотеки C++ для отправки сообщений по именованному каналу.Получение РУЧКИ к именованной трубе, открытой во внешнем процессе (win32)

Зритель журнал запускается клиентом через С ++ Lib, когда вошедшего 1-е сообщение, и делает

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); 

Я хотел бы получить РУЧКУ, которая соответствует этой именованной трубе. Документация предполагает, что я мог бы просто сделать это с помощью CreateFile(WindowPipeName(), GENERIC_READ|GENERIC_WRITE,...OPEN_EXISTING,...). Когда я делаю это, что-то явно начинает блокироваться, и просмотрщик журналов больше не получает никаких сообщений. И это даже не делает ничего с этой РУЧКОЙ.

Можно ли делать то, что я хочу, и если да, то как?

+0

См. Раздел комментариев на странице MSDN «CreateNamedPipe»: «Хотя MSDN говорит, что трубы могут быть двунаправленными, вы не должны неправильно понимать это в том смысле, что обе стороны могут одновременно слушать данные. ReadFile() выполненный на обоих концах трубы одновременно, может привести к тому, что следующая команда WriteFile() будет висела навсегда. "_. 'CallNamedPipe' - это в основном« WriteFile », за которым следует« ReadFile », за которым следует« CloseHandle ». – Damon

+0

Хех, конечно, нет - и я не делал ничего из этого AFAIK. Я передал только символы чтения + записи в CreateFile, чтобы соответствовать режиму, выбранному в CreateNamedPipe, но никогда не использовал файл HANDLE. Почему CallNamedPipe делает ReadFile (и я предполагаю, что он сначала открывает HANDLE, если он заканчивается закрытием;))? – RJVB

+0

Как в документах: _ «** Подключает ** к каналу типа сообщения (и ожидает, если экземпляр канала недоступен), ** записывает ** на и ** читает ** из канала и то ** закрывает ** трубу ». Итак, да, это все 4 операции, это то, что должна выполнять функция. Не спрашивайте меня, почему кто-то счел полезным использовать такую ​​функцию. – Damon

ответ

1

Петля для просмотра журнала начинается с вызова ConnectNamedPipe. Поэтому он ожидает, что клиент подключится, прочитает сообщение, вернется в начало цикла и ждет, когда клиент снова подключится.

Это работает с CallNamedPipe, потому что эта функция соединяется и отключается при каждом отправке сообщения.

Но если клиент создает постоянное соединение, открыв ручку в трубе с помощью CreateFile, тогда он будет подключаться только один раз. На сервере второй вызов ConnectNamedPipe будет зависать, ожидая подключения другого клиента.

Если вы хотите, чтобы просмотрщик журналов обрабатывал только один клиент с постоянным подключением, вы можете получить цикл, который вызывает ConnectNamedPipe, а затем внутренний цикл, который обрабатывает сообщения от клиента до закрытия канала.

Если вы хотите обрабатывать несколько клиентов, то ваше текущее решение намного проще, чем пытаться обрабатывать несколько одновременных подключений.

+0

Хорошо, спасибо, это объясняет некоторые другие проблемы I когда вы регистрируетесь слишком часто ...и что на стороне клиента нет РУЧКИ, за исключением вызовов CallNamedPipe. Кстати, блокировка, которую я заметил, была на стороне клиента, средство просмотра журналов, похоже, не блокировало, насколько это разрешено реакцией на обсуждение. – RJVB