异步了NamedPipes的情况下,多管服务器实例 [英] Async NamedPipes in case of multiple pipe server instances
问题描述
我用code从 <强>这篇文章 与只相差 maxNumberOfServerInstances 设置为 1 (使用相同的管道名称服务器实例的数量只受系统限制资源)的 NamedPipeServerStream 构造
I'm using code from this article with only difference that maxNumberOfServerInstances is set to -1 (number of server instances with the same pipe name is limited only by system resources) in NamedPipeServerStream constructor
异步听法[试听服务器类]:
Async Listen Method [Listen Server Class]:
class PipeServer
{
string _pipeName;
public void Listen(string PipeName)
{
try
{
// Set to class level var so we can re-use in the async callback method
_pipeName = PipeName;
// Create the new async pipe
NamedPipeServerStream pipeServer = new NamedPipeServerStream(PipeName,
PipeDirection.In, -1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
// Wait for a connection
pipeServer.BeginWaitForConnection
(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}
catch (Exception oEX)
{ ... }
}
private void WaitForConnectionCallBack(IAsyncResult iar)
{
try
{
// Get the pipe
NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
// End waiting for the connection
pipeServer.EndWaitForConnection(iar);
// Read the incoming message
byte[] buffer = new byte[255];
pipeServer.Read(buffer, 0, 255);
// Convert byte buffer to string
string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
...
// Kill original sever and create new wait server
pipeServer.Close();
pipeServer = null;
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In,
-1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
// Recursively wait for the connection again and again....
pipeServer.BeginWaitForConnection(
new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}
catch
{ ... }
}
}
异步发送方法[PipeClient类]
Async Send Method [PipeClient Class]
class PipeClient
{
public void Send(string SendStr, string PipeName, int TimeOut = 1000)
{
try
{
NamedPipeClientStream pipeStream = new NamedPipeClientStream
(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous);
// The connect function will indefinitely wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect(TimeOut);
byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
pipeStream.BeginWrite
(_buffer, 0, _buffer.Length, new AsyncCallback(AsyncSend), pipeStream);
}
catch (TimeoutException oEX)
{ ... }
}
private void AsyncSend(IAsyncResult iar)
{
try
{
// Get the pipe
NamedPipeClientStream pipeStream = (NamedPipeClientStream)iar.AsyncState;
// End the write
pipeStream.EndWrite(iar);
pipeStream.Flush();
pipeStream.Close();
pipeStream.Dispose();
}
catch (Exception oEX)
{ ... }
}
}
和我有两个的WinForms应用程序:服务器只有听按钮(点击导致Listen方法调用),客户端的文本框输入文本和发送按钮(点击结果在发送方法调用)。
And I have two WinForms applications: server only have Listen button (clicking results in Listen method call), client has textBox for text input and Send button (clicking results in Send method call).
我做到以下几点:
- 在启动服务器应用程序的多个副本(作为结果 - 的多个实例的 NamedPipeServerStream 使用相同的管道名称创建)
- 点击听在他们每个人的按钮
- 在启动客户端应用程序
- 点击发送按钮
- start multiple copies of server application (as the result - multiple instances of NamedPipeServerStream with the same pipe name are created)
- click Listen button in each of them
- start client application
- click Send button
这导致通过的只有一台服务器的应用程序接收消息(那一个,他的听按钮被点击了第一次)。如果我点击发送按钮一次 - 接收第二点击的服务器应用程序的消息。所以实例收到订单pressing信息听按钮的他们,重复的周期(但我不是100%肯定该命令的将是相同的所有条件下)。
That results in receiving message by only one server application (that one, whose Listen button was clicked first). If I click Send button one more time - message is received by second-clicked server application. So instances receive messages in order of pressing Listen button on them and that repeats in cycle (but I'm not 100% sure that such order will be the same under all conditions).
这样的行为很奇怪,我。我预计在收到消息的在同一时间的所有实例
Such behavior is strange for me: I've expected message to be received by all instances at the same time.
有人能解释我为什么它是发生在这样的方式?
Could someone explain me why it is happening in such way?
我如何可以提供消息给所有instaces一个发送按钮点击?
How can I deliver message to all instaces with one Send button click?
推荐答案
所以最后我找到了一个解决方案(不肯定这是最优的 - 但它的工作)。它是基于使用的 NamedPipeClientStream.NumberOfServerInstances
So finally I've found a solution (don't sure it's optimal - but it's working). It is based on using NamedPipeClientStream.NumberOfServerInstances.
public void Send(string SendStr, string PipeName, int TimeOut = 1000)
{
try
{
NamedPipeClientStream pipeStream = new NamedPipeClientStream
(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous);
// The connect function will indefinitely wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect(TimeOut);
int _serverCount = pipeStream.NumberOfServerInstances;
byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
pipeStream.BeginWrite(_buffer, 0, _buffer.Length, new AsyncCallback(AsyncSend), pipeStream);
//there is more than 1 server present
for (int i = 1; i < _serverCount; i++)
{
//create another client copy and use it
NamedPipeClientStream pipeStream2 = new NamedPipeClientStream
(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous);
pipeStream2.Connect(TimeOut);
byte[] buffer2 = Encoding.UTF8.GetBytes(SendStr);
pipeStream2.BeginWrite(buffer2, 0, buffer2.Length, AsyncSend, pipeStream2);
}
}
catch (TimeoutException oEX)
{ ... }
}
请注意,此code doensn't处理情况时,while循环运行(突发服务器实例关闭,等。)NumberOfServerInstances变化
Note that this code doensn't handle situation when NumberOfServerInstances changes while cycle is running (sudden server instance closing, etc.)
BTW 不要有任何想法,为什么MSDN建议使用
BTW Don't have any idea why MSDN suggests to use
// Kill original sever and create new wait server
pipeServer.Close();
pipeServer = null;
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In,
-1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
// Recursively wait for the connection again and again....
pipeServer.BeginWaitForConnection(
new AsyncCallback(WaitForConnectionCallBack), pipeServer);
相反,我测试过只要断开当前客户端
Instead I've tested simply disconnecting current client
pipeServer.Disconnect();
// Recursively wait for the connection again and again....
pipeServer.BeginWaitForConnection(
new AsyncCallback(WaitForConnectionCallBack), pipeServer);
和它的工作对我来说同样如此。
and it worked for me the same way.
这篇关于异步了NamedPipes的情况下,多管服务器实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!