Gewusst wie: Verwenden von benannten Pipes zur Kommunikation zwischen Prozessen über ein Netzwerk
Aktualisiert: November 2007
Benannte Pipes bieten mehr Funktionen als anonyme Pipes. Diese Funktionen umfassen Vollduplexkommunikation über ein Netzwerk und mehrere Serverinstanzen, meldungsbasierte Kommunikation und Clientidentitätswechsel, die verbindenden Prozessen die Verwendung ihrer eigenen Berechtigungen auf Remoteservern ermöglichen.
Beispiel
Das folgende Beispiel zeigt, wie eine benannte Pipe mit der NamedPipeClientStream-Klasse erstellt wird. In diesem Beispiel erstellt der Serverprozess vier Threads. Jeder Thread kann eine Clientverbindung akzeptieren. Der verbundene Clientprozess sendet daraufhin einen Dateinamen an den Server. Wenn der Client über ausreichende Berechtigungen verfügt, öffnet der Serverprozess die Datei und sendet ihren Inhalt an den Client zurück.
Imports System
Imports System.IO
Imports System.IO.Pipes
Imports System.Threading
Class PipeServer
Shared numThreads As Integer = 4
Shared Sub Main()
Dim i As Integer
For i = 1 To numThreads
Dim newThread As New Thread(New ThreadStart(AddressOf ServerThread))
newThread.Start()
Next
End Sub
Private Shared Sub ServerThread()
Dim pipeServer As New NamedPipeServerStream("testpipe", _
PipeDirection.InOut, numThreads)
Console.WriteLine("NamedPipeServerStream thread created.")
' Wait for a client to connect
pipeServer.WaitForConnection()
Console.WriteLine("Client connected.")
Try
' Read the request from the client. Once the client has
' written to the pipe, its security token will be available.
Dim sr As New StreamReader(pipeServer)
Dim sw As New StreamWriter(pipeServer)
sw.AutoFlush = True
' Verify our identity to the connected client using a
' string that the client anticipates.
sw.WriteLine("I am the true server!")
' Obtain the filename from the connected client.
Dim filename As String = sr.ReadLine()
' Read in the contents of the file while impersonating
' the client.
Dim fileReader As New ReadFileToStream(pipeServer, filename)
' Display the name of the clientr we are impersonating.
Console.WriteLine("Reading file: {0} as user {1}.", _
filename, pipeServer.GetImpersonationUserName())
pipeServer.RunAsClient(AddressOf fileReader.Start)
pipeServer.Disconnect()
sr.Close()
sw.Close()
Catch ex As Exception
Console.WriteLine("ERROR: {0}", ex.Message)
End Try
pipeServer.Close()
End Sub
End Class
Public Class ReadFileToStream
Private m_filename As String
Private m_stream As Stream
Public Sub New(ByVal stream1 As Stream, ByVal filename As String)
m_filename = filename
m_stream = stream1
End Sub
Public Sub Start()
Using sw As New StreamWriter(m_stream)
Dim contents As String = File.ReadAllText(m_filename)
sw.WriteLine(contents)
sw.Flush()
End Using
End Sub
End Class
using System;
using System.IO;
using System.IO.Pipes;
using System.Threading;
class PipeServer
{
static int numThreads = 4;
static void Main()
{
for (int i = 0; i < numThreads; i++)
{
Thread newThread = new Thread(new ThreadStart(ServerThread));
newThread.Start();
}
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
} // Main()
private static void ServerThread()
{
using (NamedPipeServerStream pipeServer =
new NamedPipeServerStream("testpipe", PipeDirection.InOut, numThreads))
{
Console.WriteLine("NamedPipeServerStream thread created.");
// Wait for a client to connect
pipeServer.WaitForConnection();
Console.WriteLine("Client connected.");
try
{
// Read the request from the client. Once the client has
// written to the pipe its security token will be available.
using (StreamReader sr = new StreamReader(pipeServer))
using (StreamWriter sw = new StreamWriter(pipeServer))
{
sw.AutoFlush = true;
// Verify our identity to the connected client using a
// string that the client anticipates.
sw.WriteLine("I am the true server!");
// Obtain the filename from the connected client.
string filename = sr.ReadLine();
// Read in the contents of the file while impersonating
// the client.
ReadFileToStream fileReader = new
ReadFileToStream(pipeServer, filename);
// Display the name of the user we are impersonating.
Console.WriteLine("Reading file: {0} as user {1}.",
pipeServer.GetImpersonationUserName(), filename);
pipeServer.RunAsClient(fileReader.Start);
pipeServer.Disconnect();
}
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
}
} // ServerThread()
} // PipeServer
class ReadFileToStream
{
private string m_filename;
private Stream m_stream;
public ReadFileToStream(Stream stream, string filename)
{
m_filename = filename;
m_stream = stream;
} // ReadFileToStream(stream, filename)
public void Start()
{
using (StreamWriter sw = new StreamWriter(m_stream))
{
string contents = File.ReadAllText(m_filename);
sw.WriteLine(contents);
sw.Flush();
}
} // Start()
} // ReadFileToStream
Das folgende Beispiel zeigt den Clientprozess, der die NamedPipeClientStream-Klasse verwendet. Der Client stellt eine Verbindung mit dem Serverprozess her und sendet einen Dateinamen an den Server. Anschließend sendet der Server den Inhalt der Datei an den Client zurück. Der Inhalt der Datei wird daraufhin auf der Konsole angezeigt.
Imports System
Imports System.IO
Imports System.IO.Pipes
Imports System.Security.Principal
Class PipeClient
Shared Sub Main(ByVal args As String())
Try
Dim pipeClient As New NamedPipeClientStream("localhost", _
"testpipe", PipeDirection.InOut, PipeOptions.None, _
TokenImpersonationLevel.Impersonation)
Dim sw As New StreamWriter(pipeClient)
Dim sr As New StreamReader(pipeClient)
sw.AutoFlush = True
pipeClient.Connect()
' Verify that this is the "true server"
'Dim serverID As String = sr.ReadLine()
If 1 = 1 Then
' The client security token is sent with the first write
sw.WriteLine("c:\textfile.txt")
' Print the file to the screen.
Dim buffer(32) As Char
Dim n As Integer
n = sr.Read(buffer, 0, buffer.Length)
While Not n = 0
Console.Write(buffer, 0, n)
End While
Else
Console.WriteLine("Server could not be verified.")
End If
sw.Close()
sr.Close()
pipeClient.Close()
Catch ex As Exception
Console.WriteLine("ERROR: {0}", ex.Message)
End Try
End Sub
End Class
using System;
using System.IO;
using System.IO.Pipes;
using System.Security.Principal;
class PipeClient
{
static int numThreads = 4;
static void Main()
{
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream("localhost", "testpipe",
PipeDirection.InOut, PipeOptions.None,
TokenImpersonationLevel.Impersonation))
using (StreamWriter sw = new StreamWriter(pipeClient))
using (StreamReader sr = new StreamReader(pipeClient))
{
sw.AutoFlush = true;
pipeClient.Connect();
// Verify that this is the "true server"
if (sr.ReadLine() == "I am the true server!")
{
// The client security token is sent with the first write.
sw.WriteLine(@"c:\textfile.txt");
// Print the file to the screen.
char[] buffer = new char[32];
int n;
while ((n = sr.Read(buffer, 0, buffer.Length)) != 0)
{
Console.Write(buffer, 0, n);
}
}
else
{
Console.WriteLine("Server could not be verified.");
}
}
} // Main()
}
Robuste Programmierung
Der Client- und der Serverprozess in diesem Beispiel sind zur Ausführung auf dem gleichen Computer vorgesehen, sodass der Servername, der dem NamedPipeClientStream-Objekt bereitgestellt wird, "localhost" lautet. Wenn der Client- und der Serverprozess auf verschiedenen Computern ausgeführt würden, würde "localhost" durch den Netzwerknamen des Computers ersetzt, auf dem der Serverprozess ausgeführt wird.
Siehe auch
Aufgaben
Gewusst wie: Verwenden von anonymen Pipes zur Kommunikation zwischen lokalen Prozessen