C++ 多客户端管道连接?

C++ 多客户端管道连接?,c++,c,winapi,pipe,named-pipes,C++,C,Winapi,Pipe,Named Pipes,是否可以创建多客户端管道?使用一台服务器和多个客户端?从官方文档中,我读到“管道服务器可以使用单个管道实例通过依次连接和断开每个客户机来连接多个管道客户机,但性能会很差”()。这是行为标准(可以使用一些标志或类似的东西)还是我必须自己实现这一行为?我已经用多个客户端编写了一个测试,但是当我试图用第二个客户端连接时,我得到了错误状态“管道”不可用 这是我的代码,它相当大,但函数test\u multiple\u client和test\u multiple\u client2是相同的 void t

是否可以创建多客户端管道?使用一台服务器和多个客户端?从官方文档中,我读到“管道服务器可以使用单个管道实例通过依次连接和断开每个客户机来连接多个管道客户机,但性能会很差”()。这是行为标准(可以使用一些标志或类似的东西)还是我必须自己实现这一行为?我已经用多个客户端编写了一个测试,但是当我试图用第二个客户端连接时,我得到了错误状态“管道”不可用

这是我的代码,它相当大,但函数test\u multiple\u client和test\u multiple\u client2是相同的

void test_mutiple_client( PVOID arg )
{
    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING us;
    IO_STATUS_BLOCK iosb;
    HANDLE thread = 0, event = 0, client = 0;
    NTSTATUS r;
    CLIENT_ID id;
    LARGE_INTEGER timeout;
    ULONG i;

    us.Buffer = pipename;
    us.Length = sizeof pipename - 2;
    us.MaximumLength = us.Length;

    oa.Length = sizeof oa;
    oa.RootDirectory = 0;
    oa.ObjectName = &us;
    oa.Attributes = OBJ_CASE_INSENSITIVE;
    oa.SecurityDescriptor = 0;
    oa.SecurityQualityOfService = 0;

    r = NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, NotificationEvent, 0 );
    ok(r == STATUS_SUCCESS, "return wrong (%08lx)\n", r);


    r = NtOpenFile( &client, GENERIC_READ | GENERIC_WRITE, &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0 );
    ok(r == STATUS_SUCCESS, "return wrong %08lx\n", r);
    dprintf("mc: client1 pipe created\n");

    int thread_id = __sync_add_and_fetch(&g__clientsCounter, 1);
    while (g__clientsCounter != 2);
    dprintf("thread %d stated\n", thread_id);

    r = NtReadFile( client, event, 0, 0, &iosb, &i, sizeof i, 0, 0 );
    if (r == STATUS_PENDING)
        r = NtWaitForSingleObject( event, TRUE, 0 );
    ok (r == STATUS_SUCCESS, "read %ld returned %08lx\n", i, r);
    ok (i == 13, "lol?????");

    r = NtClose( client );
    ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);

}

void test_mutiple_client2( PVOID arg )
{
    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING us;
    IO_STATUS_BLOCK iosb;
    HANDLE thread = 0, event = 0, client = 0;
    NTSTATUS r;
    CLIENT_ID id;
    LARGE_INTEGER timeout;
    ULONG i;

    us.Buffer = pipename;
    us.Length = sizeof pipename - 2;
    us.MaximumLength = us.Length;

    oa.Length = sizeof oa;
    oa.RootDirectory = 0;
    oa.ObjectName = &us;
    oa.Attributes = OBJ_CASE_INSENSITIVE;
    oa.SecurityDescriptor = 0;
    oa.SecurityQualityOfService = 0;

    r = NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, NotificationEvent, 0 );
    ok(r == STATUS_SUCCESS, "return wrong (%08lx)\n", r);


    r = NtOpenFile( &client, GENERIC_READ | GENERIC_WRITE, &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0 );
    ok(r == STATUS_SUCCESS, "return wrong %08lx\n", r);
    dprintf("mc: client1 pipe created\n");

    int thread_id = __sync_add_and_fetch(&g__clientsCounter, 1);
    while (g__clientsCounter != 2);
    dprintf("thread %d stated\n", thread_id);

    r = NtReadFile( client, event, 0, 0, &iosb, &i, sizeof i, 0, 0 );
    if (r == STATUS_PENDING)
        r = NtWaitForSingleObject( event, TRUE, 0 );
    ok (r == STATUS_SUCCESS, "read %ld returned %08lx\n", i, r);
    ok (i == 13, "lol?????");

    r = NtClose( client );
    ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);

}

void test_multiple_connections( )
{
    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING us;
    IO_STATUS_BLOCK iosb;
    HANDLE pipe = 0, thread = 0, event = 0;
    NTSTATUS r;
    CLIENT_ID id;
    LARGE_INTEGER timeout;
    ULONG i;

    us.Buffer = pipename;
    us.Length = sizeof pipename - 2;
    us.MaximumLength = us.Length;

    oa.Length = sizeof oa;
    oa.RootDirectory = 0;
    oa.ObjectName = &us;
    oa.Attributes = OBJ_CASE_INSENSITIVE;
    oa.SecurityDescriptor = 0;
    oa.SecurityQualityOfService = 0;

    timeout.QuadPart = -10000LL;
    r = NtCreateNamedPipeFile( &pipe, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
                &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, TRUE,
                TRUE, FALSE, /*Unlimited*/ -1, 0, 0, &timeout );
    ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);
    dprintf("mc: server pipe created\n");

    r = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE,
                                 NULL, 0, 0, &test_mutiple_client, NULL, &thread, &id );
    ok( r == STATUS_SUCCESS, "failed to create thread\n" );

    r = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE,
                                 NULL, 0, 0, &test_mutiple_client2, NULL, &thread, &id );
    ok( r == STATUS_SUCCESS, "failed to create thread\n" );

    r = NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, NotificationEvent, 0 );
    ok(r == STATUS_SUCCESS, "return wrong (%08lx)\n", r);


    r = NtFsControlFile( pipe, event, 0, 0, &iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0 );
    if (r == STATUS_PENDING) {
        dprintf("mc: pending\n");
        r = NtWaitForSingleObject( event, TRUE, 0 );
    }
    ok( r == STATUS_SUCCESS, "failed to listen %08lx\n", r );
    dprintf("mc: server pipe listen\n");

    i = 13;

    while (g__clientsCounter != 2);
    dprintf("server started\n");

    r = NtWriteFile( pipe, event, 0, 0, &iosb, &i, sizeof i, 0, 0 );
    if (r == STATUS_PENDING)
        r = NtWaitForSingleObject( event, TRUE, 0 );
    ok (r == STATUS_SUCCESS, "write %ld returned %08lx\n", i, r);
    dprintf("server write data\n");


    r = NtClose( pipe );
    ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);

}
输出是

mc: server pipe created
mc: pending
mc: server pipe listen
mc: client1 pipe created
478: return wrong c00000ac
mc: client1 pipe created
thread 2 stated
488: read 2013057864 returned c0000008
489: lol?????492: return wrong c0000008
server started
thread 1 stated
server write data
4 failed, 38 passed

我还看到了stack()的答案,其中提到windows管道最多可以容纳256个客户端

为什么您认为可以在windows下使用NtCreateFile创建管道?为什么您使用较低级别的NT函数而不是较高级别的内核函数?在任何情况下,要并行处理多个客户机,请为每个连接的客户机使用单独的线程,或者使用重叠的I/O。这是内核模式代码吗?@HarryJohnston是的,它是未记录的isRtlCreateUserThread(因此您无论如何都不应该使用它),但根据我在internet上找到的信息,它创建了一个用户模式线程,它将无法运行内核模式代码。您可能需要PsCreateSystemThread。