我使用this article中的代码,区别在于 maxNumberOfServerInstances 设置为 -1 (具有相同管道名称的服务器实例数)仅受 NamedPipeServerStream 构造函数
中的系统资源限制异步侦听方法[侦听服务器类]:
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类]
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方法调用中的结果),客户端有textBox用于文本输入和发送按钮(单击结果在Send方法调用中。
我执行以下操作:
这会导致仅接收一个服务器应用程序(首先点击 Listen 按钮的那个)接收消息。如果我再次单击发送按钮 - 第二次单击的服务器应用程序会收到消息。因此,实例按顺序接收消息,按下倾听按钮,并在循环中重复(但我不能100%确定此类订单在所有情况下都是相同的)。
这种行为对我来说很奇怪:我希望所有实例同时收到消息。
有人能解释一下为什么会这样发生吗?
如何通过单击发送按钮向所有实例发送消息?
答案 0 :(得分:1)
所以最后我找到了一个解决方案(不确定它是否是最佳的 - 但它能够正常工作)。它基于使用 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)
{ ... }
}
请注意,当循环运行(突然关闭服务器实例等)时NumberOfServerInstances发生更改时,此代码不会处理这种情况。
BTW 不知道MSDN建议使用的原因
// 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);
相反,我测试的只是断开当前客户端
pipeServer.Disconnect();
// Recursively wait for the connection again and again....
pipeServer.BeginWaitForConnection(
new AsyncCallback(WaitForConnectionCallBack), pipeServer);
它以同样的方式为我工作。