NamedPipeServerStream/async可靠断开连接问题 [英] NamedPipeServerStream/async reliable disconnect issues

查看:172
本文介绍了NamedPipeServerStream/async可靠断开连接问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用命名管道在C#.Net服务和本机C ++应用程序之间进行通信.该服务创建一个消息模式管道,然后启动一个计时器.

We're using named pipes to communicate between a C# .Net service and a native C++ application. The service creates a message mode pipe, then kicks off a timer.

     m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",
                                             PipeDirection.InOut,
                                             1,
                                             PipeTransmissionMode.Message,
                                             PipeOptions.Asynchronous,
                                             4096,
                                             4096,
                                             pipeSa);
     m_OutputQueue = new List<My_Message>();

在计时器滴答例程中是主要的服务循环,如下所示:

In the timer tick routine is the main service loop, which looks like this:

     do
     {
        if (!m_bClientAttached)
        {
           try
           {
              m_pipeServer.WaitForConnection ();
              m_bClientAttached = true;
           }
           catch (InvalidOperationException invope)
           {
              sDebug = string.Format ("Pipe wait exception InvOpEx: {0}",
                                      invope.Message);
              DebugMessage (sDebug);
           }
        }

        // the message-pumping part of the loop. 

        if (m_bClientAttached)
        {
           try
           {
              if (!m_bReadInProgress)
              {
                 m_bReadInProgress = true;
                 m_pipeServer.BeginRead (byNewRead, 0, byNewRead.GetLength (0),
                                       new AsyncCallback (this.PipeReadComplete),
                                       m_iReadCount);
              }

              if (m_OutputQueue.Count () > 0)
              {
                 if (!m_bWriteInProgress)
                 {
                    m_bWriteInProgress = true;
                    My_Message opmsg = m_OutputQueue.ElementAt (0);
                    m_pipeServer.BeginWrite (opmsg.ToByteArray (), 0,
                                             (int)(opmsg.MsgLength),
                                             new AsyncCallback (this.PipeWriteComplete),
                                             m_iWriteCount);
                 }
              }
           }
           catch (IOException ioe)
           {
              sDebug = string.Format ("Main loop raised exception: {1}",
                                      ioe.Message);
              DebugMessage (sDebug);
              DetachClientPipe();
           }
           Thread.Sleep(1);
        }

     } while (m_bRunning);

     m_pipeServer.Close ();
  }

读写完成例程如下:

  private void PipeReadComplete (IAsyncResult iAR)
  {
     string sDebug;
     int iByteCount;
     My_Message ipmsg = new My_Message();
     try
     {
        iByteCount = m_pipeServer.EndRead (iAR);
        if (iByteCount > 0) 
        {
           ipmsg.FromByteArray(byNewRead);
           m_bReadInProgress = false;
           ... process message ...
        }
        else
        {
           try
           {
              DebugMessage ("PRC: Zero bytes read, disconnect pipe");
              DetachClientPipe();
           }
           catch (InvalidOperationException invope)
           {
              sDebug = string.Format ("PRC - Pipe disconnect exception: {0}",
                                      invope.Message);
              DebugMessage (sDebug);
           }
        }
     }
     catch (IOException e)
     {
        sDebug = string.Format ("PRC: Read {0} raised exception: {1}",
                                (int)(iAR.AsyncState),
                                e.Message);
        DebugMessage (sDebug);
        DetachClientPipe();
     }
  }

  // ------------------------------------------------------------------

  private void PipeWriteComplete (IAsyncResult iAR)
  {
     string sDebug;
     try
     {
        m_pipeServer.EndWrite (iAR);
        lock (m_OutputQueue)
        {
           m_OutputQueue.RemoveAt(0);
        }
        m_bWriteInProgress = false;
     }
     catch (IOException e)
     {
        sDebug = string.Format ("Write {0} raised exception: {1}",
                                (int)(iAR.AsyncState),
                                e.Message);
        DebugMessage (sDebug);
        DetachClientPipe();
     }
  }

  // ------------------------------------------------------------------

  private void DetachClientPipe()
  {
     if (m_pipeServer.IsConnected)
     {
        m_pipeServer.Disconnect();
     }
     m_bClientAttached = false;
  }

客户端代码是已知的好代码,可以重复使用.这就是问题所在.客户端可以正常连接.然后,我们关闭客户端,一切都很好.我们启动并再次连接.一切正常,然后我们将其关闭,然后重新启动.动臂-错误231,管道繁忙.服务器现在将在任何连接尝试上生成管道繁忙错误,直到地狱死机,或者我们重新启动该服务.然后,我们又回到两个连接.

The client side code is known good code, re-used. So here's the problem. The client can connect fine. We then shut down the client, everything is fine. We start it up and conect again. All fine, then we close it and start it again. Boom - error 231, pipe busy. the server will now generate pipe busy errors on any connection attempt until hell freezes over, or we restart the service. Then we're back to two connections again.

我已经连续三天盯着这段代码了,我也不知道为什么要这么做.我似乎看不到树木所用的木头,我可以用一双或三只新鲜的眼睛.问题是团队中没有其他人知道任何C#.

I've been staring at this code for three straight days now, and I have no idea why it does this. I can't seem to see the wood for the trees, and I could use a fresh pair of eyes or three. Problem is no-one else in the team knows much of any C#.

更新

Update

在第三次连接尝试中失败的原因似乎是,在第一次断开连接时,PipeReadComplete返回并且读取了零字节,因此我分离了管道,一切都很好.但是...在第二次断开连接时,不会调用PipeReadComplete,因此我不强制断开连接.很奇怪.

The reason this fails on the third connect attempt appears to be that on the first disconnect the PipeReadComplete returns and I get zero bytes read, so I detach the pipe and all is well. BUT... on the second disconnection, PipeReadComplete does NOT get called, so I don't force the disconnect. Weird.

推荐答案

鲍勃(Bob),一个快速解决方案:想知道,您是否尝试将服务器实例参数设置为大于1的值,然后看两次尝试后它是否仍然失败?而不是1,放10,看看是否有帮助.同样,如果您也发布非托管代码,这也将有所帮助.我目前正在做同样的事情,Windows服务以及非托管DLL IPC.

Bob, for a quick fix: was wondering, have you tried setting the server instance parameter to more than 1 and see if it still fails after 2 tries? Instead of 1, put 10 and see if it will help things. Also, it will help if you post the unmanaged code as well. I'm currently doing the same thing, windows service plus unmanaged dll IPC.

    m_pipeServer = new NamedPipeServerStream  ("Cyber_Srv_EventPipe",    
                                         PipeDirection.InOut,              
                                         10,
                                         PipeTransmissionMode.Message,  
                                         PipeOptions.Asynchronous,                                                 
                                         4096,
                                         4096,
                                         pipeSa);       

还是您实际上始终始终只需要一个服务器管道实例?

Or you actually need to have only one server pipe instance at all times?

这篇关于NamedPipeServerStream/async可靠断开连接问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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