代码之家  ›  专栏  ›  技术社区  ›  Bob Moore

NamedPipeServerStream/async可靠断开连接问题

  •  0
  • Bob Moore  · 技术社区  · 15 年前

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

    在timer tick例程中是主服务循环,如下所示:

         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,管道忙。服务器现在将在任何连接尝试上生成管道忙错误,直到hell冻结,或者我们重新启动服务。然后我们又回到两个连接。

    我已经连续三天盯着这个代码看了,我不知道它为什么会这样。我好像看不见树木的树林,我需要一双或三双新眼睛。问题是团队中没有人知道很多C#。

    更新

    2 回复  |  直到 15 年前
        1
  •  1
  •   Bryan Lee    13 年前

    Bob,快速修复:想知道,您是否尝试过将服务器实例参数设置为大于1,并在两次尝试后查看它是否仍然失败?不是1,而是10,看看它是否有帮助。另外,如果您也发布非托管代码,它也会有帮助。我正在做同样的事情,windows服务加上非托管dll IPC。

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

    或者您实际上在任何时候都只需要一个服务器管道实例?

        2
  •  0
  •   Community CDub    7 年前

    this related question 可能的答案。看来 Suma 经历并解决了同样的问题,虽然不是用C#,但应该很容易翻译。