#.net #named-pipes #namedpipeserverstream
#.net #именованные каналы #namedpipeserverstream именованный серверный поток #namedpipeserverstream
Вопрос:
У меня есть сервер именованных каналов, написанный на C #. Суть реализации заключается в:
void BeginWaitForNextConnection()
{
var pipe = new NamedPipeServerStream(
PipeName,
PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous,
0, // default in buffer size
0, // default out buffer size
CreateAllAccessPipeSecurity());
pipe.BeginWaitForConnection(ClientRequestHandler, pipe);
}
void ClientRequestHandler(IAsyncResult ar)
{
// Clean up the async call state.
NamedPipeServerStream pipe = (NamedPipeServerStream)ar.AsyncState;
pipe.EndWaitForConnection(ar);
// If we've been asked to shut down, go away.
if (_stopping)
{
pipe.Close();
return;
}
// Set up for the next caller.
BeginWaitForNextConnection();
// Handle this client's I/O. This code wraps the pipe stream in BinaryReader and BinaryWriter objects and handles communication with the client.
HandlePipeClient(pipe);
}
Это работает совершенно нормально — до тех пор, пока несколько экземпляров не попытаются подключиться в быстрой последовательности. В моем клиентском коде указан 10-секундный тайм-аут, поэтому я ожидаю, что даже если 10 экземпляров попытаются подключиться в одну и ту же секунду, все они должны быть успешными, потому что этому коду не должно потребоваться 10 секунд, чтобы выполнить цикл из 10 итераций ClientRequestHandler
обратных вызовов через BeginWaitForNextConnection
— но это действительно то, что я вижу. Для случайного одноразового подключения этот код очень надежен, но если я обращаюсь к нему с частыми запросами, оказывается, что, возможно, если запрос на соединение поступает между обратным вызовом и следующим BeginWaitForConnection
, это соединение не ставится в очередь и не перехватывается немедленно — оно просто теряется.
Ожидаемо ли это?? Каково идиоматически правильное решение? Должен ли я просто разматывать целую кучу потоков, все ожидающие соединений одновременно?
Комментарии:
1. Я просто потратил некоторое время, пытаясь создать минимальное воспроизведение проблемы. Я могу воспроизвести это довольно надежно — хотя, как ни странно, кажется, что одним из волшебных ингредиентов является использование командной оболочки Take для автоматизации. Если я просто напишу программу, которая запускает клиентов как можно быстрее, используя
Process.Create
, то, похоже, проблему невозможно вызвать, даже при максимально быстром запуске 100 клиентов. Но, если я войду в TCCfor /L %i in (1,1,50) do start Client.exe
, тогда значительное, но непредсказуемое количество клиентов не сможет подключиться к серверу.2. Если я запускаю свой драйвер дважды подряд, оба раза каждый клиент завершается успешно. Если я использую TCC automation и получаю ошибки, а затем сразу после этого запускаю свой драйвер, у экземпляров, созданных моим драйвером, также возникают проблемы. Похоже, что что -то, что делает TCC, вызывает какую-то проблему с ресурсами канала, но я не могу представить, что бы это могло быть.
Ответ №1:
У меня была похожая потребность.
В итоге я получил серверный поток для каждого соединения, причем каждый поток создавался сразу после предыдущего клиентского соединения.
private void ServerConnectToPipe()
{
var bw = new BackgroundWorker();
bw.DoWork = (s, e) => DoServerStuff();
bw.RunWorkerAsync();
}
private void DoServerStuff()
{
var serverStream = new NamedPipeServerStream("PipeName", PipeDirection.In, NamedPipeServerStream.MaxAllowedServerInstances);
var streamReader = new StreamReader(serverStream);
serverStream.WaitForConnection();
ServerConnectToPipe();
Log("Server connection", $"Client connected !");
while (true)
{
var line = streamReader.ReadLine();
// do stuff
}
}