Не можете открыть Windows Named Pipe для записи? - PullRequest
0 голосов
/ 29 октября 2018

Я не понимаю, почему я даже не могу открыть именованный канал для записи, которую я создал в другом процессе.

Я получаю ошибку

231 (все экземпляры канала заняты).

Автор (клиент):

#include "Windows.h"
#include <stdio.h>
#include <errno.h>

int main()
{
    HANDLE hpipe;
    DWORD written;
    char msg[] = "play asdf.wav";

    hpipe = CreateFileA("\\\\.\\pipe\\isp-control",
               GENERIC_WRITE | GENERIC_READ,
               0, NULL, OPEN_EXISTING, 0, NULL);

    if (hpipe != INVALID_HANDLE_VALUE)
    {
      WriteFile(hpipe, msg, strlen(msg) + 1, &written, NULL);
      printf("wrote %d bytes of %d: '%s'\n", written, strlen(msg) + 1, msg);

      CloseHandle(hpipe);
    }
    else
    {
      printf("error %d opening pipe (handle %d)\n", GetLastError(), (int) hpipe);
      return 1;
    }

    return 0;
}

Считыватель (сервер) ранее создал такой канал (обратите внимание на 4 случая, так что нужно быть свободным, не так ли?)

hpipe_ = CreateNamedPipeA("\\\\.\\pipe\\isp-control",
             PIPE_ACCESS_DUPLEX,
             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
             4, // number of instances
             1024 * 16, // output buffer size
             65535,  // input size
             2000, // default timeout ms 
             NULL);

, а затем использует PeekNamedPipe, чтобы посмотреть, есть ли данные для чтения с помощью ReadFile или отправки тайм-аута.

1 Ответ

0 голосов
/ 29 октября 2018

4-й параметр CreateNamedPipe - nMaxInstances - это Максимальное количество экземпляров, которое можно создать для этой трубы.

так что это не количество экземпляров, созданных за один вызов, а максимальное количество, которое можно создать. одиночный вызов CreateNamedPipe всегда создает один (1) экземпляр канала. если вы хотите иметь 4 экземпляра - вам нужно позвонить CreateNamedPipe 4 раза. Также изначально канал создан в состоянии прослушивания, поэтому клиент может просто подключиться к нему по вызову CreateFile. но после разрыва соединения (потому что клиент закрывает сам дескриптор), и вы хотите принять новые клиентские соединения для того же экземпляра канала - вам нужно вызвать DisconnectNamedPipe, а затем ConnectNamedPipe - только после того, как этот новый клиент сможет снова подключиться к тому же экземпляру канала .

но в любом случае, даже если вы создаете только один экземпляр канала, одним вызовом CreateNamedPipeA - первый клиент может подключиться к нему. ошибка 231 - я предполагаю, что реальный источник ошибки - STATUS_PIPE_NOT_AVAILABLE ( экземпляр именованного канала не может быть находится в состоянии прослушивания ) - вы можете проверить это по телефону RtlGetLastNtStatus() после CreateFile сбой вместо GetLastError() сказать, что имя канала допустимо, нет проблем с доступом, но кто-то уже подключился (возможно, уже отключен) на канал - никогда не вызывайте CreateFile, верните эту ошибку

...