是否可以创建多客户管道?有一个服务器和多个客户端?从官方文档我已经读过"管道服务器可以使用单个管道实例通过依次连接到每个客户端和从每个客户端断开连接来连接多个管道客户端,但性能会很差。 (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365594(v=vs.85).aspx)。这种行为是标准的(可以使用某些标志或类似的东西来完成),或者我必须自己实现这种行为?我已经使用乘法客户端编写了一个测试,但是当我尝试通过第二个客户端连接时,我收到错误STATUS_PIPE_NOT_AVAILABLE。
有我的代码,它很大,但函数test_multiple_client和test_multiple_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
我也看到了堆栈(Number of Clients that can connect to a Named Pipe)的答案,其中提到windows管道最多可以容纳256个客户端