2

他のアプリケーションが単純な状態値を読み取ることができる防御的な名前付きパイプ サーバーを作成しようとしています。クライアントが接続し、状態を読み取り、切断する名前付きパイプ インスタンスを 1 つだけ持つことに関心があります。

私が抱えている問題は、パイプを不適切な使用から保護しようとすることです。具体的には、単一のプロセスが制御を取得するのを防ぎ、名前付きパイプを決して手放しません。タイムアウト後にパイプを強制的に切断/クローズして接続を終了しようとしました。この試行により、サーバーは続行できますが、接続を終了しても非同期コールバックは呼び出されません。

私のコードの最小化されたバージョンは次のとおりです(.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 に答える