Programme, welche auf demselben Computer laufen, können die sogenannte "Interprozesskommunikation" nutzen um Daten auszutauschen.
Laufen die Programme jedoch auf verschiedenen Computern, muss ein Netzwerkprotokoll genutzt werden, um Daten auszutauschen.
Dieses Mal werde ich die Interprozesskommunikation mithilfe von Pipes beschreiben, beim nächsten Mal die über das Netzwerkkommunikation mithilfe des TCP-Protokolls.
Interprozesskommunikation: Pipes
Mithilfe von benannten Pipes, kann man zwischen 2 Programmen eine Kommunikation aufbauen. Dazu braucht es eine Server-Applikation, welche die Daten empfängt und eine Client-Applikation, welche die Daten sendet.Server-Applikation
Um einen übersichtlicheren und besser wiederverwendbaren Code zu programmieren, habe ich eine Klasse namens PipeServer erstellt.Die Klasse hat 3 Klassenvariablen:
private NamedPipeServerStream serverstream;
public delegate void dMessage(object sender, MessageEventArgs e);
public event dMessage Message;
Die Klasse NamedPipeServerStream stellt den eigentlichen Pipe-Server bereit.
Das Delegate und der Event sind dazu da, um ein Event auszulösen, wenn eine Nachricht empfangen wurde.
Die Klasse MessageEventArgs, welche als Parameter verwendet wird habe ich ebenfalls selbst erstellt und enthält lediglich einen public string der die gesendeten Daten übergeben soll:
public class MessageEventArgs
{
public MessageEventArgs(string message)
{
Message = message;
}
public string Message
{
set;
get;
}
}
Im Konstruktor der PipeServer-Klasse wird ein neuer NamedPipeServerStream instanziiert, jedoch wird er noch nicht verwendet.
Da dieser PipeServer ja über einen Namen läuft, wird dieser beim Konstruktor angegeben:
public PipeServer(string name)
{
serverStream = new NamedPipeServerStream(name);
}
In einer eigenen Methode kann der PipeServer nun gestartet werden, damit er Daten empfangen kann.
Der Grund, weshalb der Server nicht direkt im Konstruktor gestartet wird ist, dass dieser somit in einen eigenen Thread ausgelagert werden kann und der Event im Objekt registriert werden kann, in dem es erstellt wurde.
Diese Start-Methode startet den Server bloss einmal, hört also bloss auf einen Client. Wenn dieser die Verbindung schliesst wird der Server beendet. Mit einer While-Schlaufe kann das ganze natürlich angepasst werden.
public void Start()
{
//Startet den Server worauf er auf eine Verbindung durch den Client wartet.
serverStream.WaitForConnection();
//Sobald sich ein Programm verbunden hat, wird ein StreamReader für den PipeServer instanziiert
StreamReader streamReader = new StreamReader(serverStream);
//Schleife wird durchloffen, bis die Verbindung vom Client getrennt wurde
while(true)
{
//Liest gesendete Daten bei jedem Flush vom Client
var data = streamReader.ReadLine();
//Überprüft ob die Verbindung offen ist und Daten gesendet wurden
if (data != null)
{
//Wenn ja wird der Message-Event ausgelöst und die erhaltenen Daten übergeben
Message(this, new MessageEventArgs(data));
}
else
{
//Wenn nein wird der Server geschlossen und die Schlaufe verlassen
serverStream.Close();
break;
}
}
}
Client-Applikation
Die Client-Applikation ist sehr simpel, jedoch muss man wissen, wie das Flush-System des StreamWriters funktioniert.Zuerst muss ein NamedPipeClientStream aufgebaut werden. Wichtig ist dabei dass er denselben Namen hat wie der NamedPipeServerStream der Server-Applikation. Ansonsten können Sie keine Verbindung aufbauen:
NamedPipeClientStream clientStream = new NamedPipeClientStream(name);
Anschliessend muss wird versucht die Verbindung zum Server aufzubauen:
clientStream.Connect();
Nun muss ein StreamWriter erstellt werden.
StreamWriter streamWriter = new StreamWriter(clientStream);
Wichtig ist nun ob man mit AutoFlush arbeiten will, oder nicht, der AutoFlush-Wert ist standardmässig auf false gesetzt.
Ohne AutoFlush wird nichts gesendet, bis man die Methode Flush des StreamWriters aufruft.
Mit AutoFlush wird jede abgeschlossene Zeile gesendet:
streamWriter.AutoFlush = true;
Nun können die Daten mit der Write bzw. der WriteLine Methode des StreamWriters gesendet werden:
streamWriter.Write("Das ist");
streamWriter.WriteLine(" ein Test");
streamWriter.Flush(); //Nur nötig wenn AutoFlush deaktiviert ist
Der Server würde nun "Das ist ein Test" erhalten.