异步了NamedPipes的情况下,多管服务器实例 [英] Async NamedPipes in case of multiple pipe server instances

查看:636
本文介绍了异步了NamedPipes的情况下,多管服务器实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用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).

我做到以下几点:

  1. 在启动服务器应用程序的多个副本(作为结果 - 的多个实例的 NamedPipeServerStream 使用相同的管道名称创建)
  2. 点击在他们每个人的按钮
  3. 在启动客户端应用程序
  4. 点击发送按钮
  1. start multiple copies of server application (as the result - multiple instances of NamedPipeServerStream with the same pipe name are created)
  2. click Listen button in each of them
  3. start client application
  4. 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆