2

我正在尝试创建一个防御性命名管道服务器,其他应用程序可以读取一个简单的状态值。我对只有一个命名管道实例感兴趣,客户端将在其中连接、读取状态和断开连接。

我遇到的问题是试图保护我的管道免受不当使用;特别是防止单个进程控制并且永远不会放开我的命名管道。我试图在超时后强制断开/关闭管道以终止连接;该尝试允许我的服务器继续,但是,当我结束连接时不会调用异步回调。

我的代码的最小化版本如下(.NET 3.5)...

服务器端]

  static AutoResetEvent autoEvent = new AutoResetEvent(false);

  static void Main(string[] args)
  {
      NamedPipeServerStream pipe = new NamedPipeServerStream("TestSimplePipe", PipeDirection.Out);

      Console.WriteLine("Waiting for client...");
      pipe.WaitForConnection();

      Console.WriteLine("About to BeginWrite...");
      pipe.BeginWrite(new byte[1] { 0x00 }, 0, 1, new AsyncCallback(ProcessWrite), pipe);

      Console.WriteLine("Waiting...");
      bool hasSignal = autoEvent.WaitOne(5000);
      if (hasSignal == false)
      {
          Console.WriteLine("Client took to long.");
      }

      Console.WriteLine("Closing pipe.");
      pipe.Close();
      Console.ReadLine();
  }

  static void ProcessWrite(IAsyncResult result)
  {
      try
      {
          Console.WriteLine("Ending write...");
          NamedPipeServerStream pipe = result.AsyncState as NamedPipeServerStream;
          pipe.EndWrite(result);

          Console.WriteLine("Wrote successfully!");
      }
      catch (Exception)
      {
          Console.WriteLine("Write not completed.");
      }

      autoEvent.Set();
  }

客户端]

  static void Main(string[] args)
  {
      using (NamedPipeClientStream npcs = new NamedPipeClientStream(".", "TestSimplePipe", PipeDirection.In))
      {
          Console.WriteLine("Connecting to server...");
          npcs.Connect();
          Console.WriteLine("Connected!");

          //Thread.Sleep(15000);

          Console.WriteLine("Reading byte...");
          npcs.ReadByte();
          Console.WriteLine("Byte read!");
      }

      Console.WriteLine("Done!");
      Console.ReadLine();
  }

如果一切都按计划设计,我会得到以下输出:

服务器端]

    Waiting for client...
    About to BeginWrite...
    Waiting...
    Ending write...
    Wrote successfully!
    Closing pipe.

客户端]

    Connecting to server...
    Connected!
    Reading byte...
    Byte read!
    Done!

但是,如果我在客户端代码中启用睡眠,服务器将不会从回调中输出任何内容:

    Waiting for client...
    About to BeginWrite...
    Waiting...
    Client took to long.
    Closing pipe.

我假设在关闭时,将调用回调并抛出“ObjectDisposedException”。相反,当我关闭服务器管道时不会调用回调。

还让我害怕的是,如果我等待客户端睡眠的整个持续时间而不结束我的服务器管道应用程序,则将在服务器上调用回调,并且我将收到服务器的以下输出:

    Waiting for client...
    About to BeginWrite...
    Waiting...
    Client took to long.
    Closing pipe.
    Ending write...
    Write not completed.

我不担心清理异步调用,但担心由于第三方应用程序它会以某种方式保持活动状态。当我终止回调附加到的管道时,如何正确清理异步回调?

4

1 回答 1

2

您可以多次打开同一个命名管道。您应该同时接受多个客户端。这样,没有单个客户端可以阻止端点。这显示在 MSDN 上的本机代码示例中。您可以将该代码移植到 .NET。可能,您应该使用异步 IO,这样您就不会用完许多客户端的线程。

另一方面,恶意客户端可能会导致资源耗尽或通过向服务器发送垃圾邮件连接而使其他客户端无法连接。我不知道有什么方法可以防止这种情况发生。

于 2013-09-05T23:34:41.190 回答