Named Pipes unter .NET
Frank Dzaebel, erstellt am: 6.2.2008, zuletzt geändert: 6.02.2008
Kategorie:Kommunikation, .NET-Version:3.5, [Download]

Im System.IO.Pipes Namespace gibt es unter anderem die .NET Klassen: NamedPipeServerStream und NamedPipeClientStream. Hier ein kleines Windows Forms Beispiel, wie man eine einfache Kommunikation aufbauen kann:



PipeServer.cs:    
using System;
using System.IO;
using System.IO.Pipes;
using System.Windows.Forms;
using System.Threading;

class PipeServer
{
  TextBox tb;
  bool abbruch = false;

  /// <summary>Wenn true, wird der Server gestoppt.</summary>
  public void Stop()
  {
    abbruch = true;
  }

  public void Start(object txtServer)
  {
    tb = (TextBox)txtServer;

    try
    {
      using (NamedPipeServerStream pipeServer =
          new NamedPipeServerStream("TestPipe", PipeDirection.Out))
      {
        ZeileAnzeigen("NamedPipeServerStream Objekt erzeugt.");

        // Warte auf Verbindung von einem Client
        ZeileAnzeigen("Warte auf Verbindung von einem Client ...");
        pipeServer.WaitForConnection();
        ZeileAnzeigen("Client verbunden!");
        // Lese die Eingabe des Benutzers und sende es zum Client Prozess.
        using (StreamWriter sw = new StreamWriter(pipeServer))
        {
          while (!abbruch)
          {
            sw.AutoFlush = true; Application.DoEvents();
            ZeileAnzeigen("\r\nBitte Text eingeben, dann Enter drücken ... :");
            tb.KeyPress -= new KeyPressEventHandler(tb_KeyPress);
            tb.KeyPress += new KeyPressEventHandler(tb_KeyPress);
            while (!enterPressed && !abbruch) Thread.Sleep(20);
            enterPressed = false;
            sw.WriteLine(toWrite);
          }
        }
      }
    }
    // Ausnahmen behandeln, wenn die Pipe unverbunden oder unbrauchbar ist.
    catch (IOException e)
    {
      ZeileAnzeigen("Fehler: {0}", e.Message);
    }
  }

  bool enterPressed = false;
  string toWrite = "";

  void tb_KeyPress(object sender, KeyPressEventArgs e)
  {
    if (e.KeyChar == (char)Keys.Enter)
    {
      enterPressed = true;
      toWrite = tb.Lines[tb.Lines.Length - 1];
      ZeileAnzeigen(". OK, sende: \"" + toWrite + "\"");
    }
  }

  #region Anzeige

  private void ZeileAnzeigen(string zeile)
  {
    tb.Invoke(new UpdateTextCallback(UpdateText),
      new object[] { zeile + "\r\n" });
  }

  private void ZeileAnzeigen(string format, params object[] arguments)
  {
    tb.Invoke(new UpdateTextCallback(UpdateText),
      new object[] { string.Format(format, arguments) });
  }

  public delegate void UpdateTextCallback(string text);

  private void UpdateText(string text)
  {
    tb.AppendText(text + Environment.NewLine);
    Application.DoEvents();
  }

  #endregion
}

PipeClient.cs:  
using System;
using System.IO;
using System.IO.Pipes;
using System.Windows.Forms;
using System.Threading;

class PipeClient
{
  TextBox tb;
  bool abbruch = false;

  /// <summary>Wenn true, wird der Client gestoppt.</summary>
  public void Stop()
  {
    abbruch = true;
  }

  public void Start(object txtClient)
  {
    this.tb = (TextBox)txtClient;

    using (NamedPipeClientStream pipeClient =
        new NamedPipeClientStream(".", "TestPipe", PipeDirection.In))
    {
      // Verbinde mit der Pipe, oder warte, bis die Pipe verfügbar ist.
      ZeileAnzeigen("Versuche die Pipe zu verbinden...");
      pipeClient.Connect();

      ZeileAnzeigen("Verbunden mit der Pipe.");
      ZeileAnzeigen("Es sind gerade {0} PipeServer Instanzen geöffnet.",
         pipeClient.NumberOfServerInstances);
      using (StreamReader sr = new StreamReader(pipeClient))
      {
        // Zeigt den gelesenen Text in der TextBox (s.Konstruktor) an.
        string temp;
        while(!abbruch)
        {
          temp = sr.ReadLine();
          if (temp != "")
            ZeileAnzeigen("Empfangen vom Server: '{0}'", temp);
          Thread.Sleep(10);
        } 
      }
    }
    ZeileAnzeigen("Der Client wurde beendet.");
  }

  #region Anzeige

  private void ZeileAnzeigen(string zeile)
  {
    tb.Invoke(new UpdateTextCallback(UpdateText),
      new object[] { zeile + "\r\n" });
  }

  private void ZeileAnzeigen(string format, params object[] arguments)
  {
    tb.Invoke(new UpdateTextCallback(UpdateText),
      new object[] { string.Format(format, arguments) });
  }

  public delegate void UpdateTextCallback(string text);

  private void UpdateText(string text)
  {
    tb.AppendText(text + Environment.NewLine);
    Application.DoEvents();
  }

  #endregion