Comment : utiliser des canaux nommés pour la communication entre processus sur un réseau
Mise à jour : novembre 2007
Les canaux nommés proposent davantage de fonctionnalités que les canaux anonymes. Parmi ces fonctionnalités figurent la communication en duplex intégral sur un réseau et plusieurs instances de serveur, la communication par messagerie et l'emprunt d'identité client, qui permet aux processus de connexion d'utiliser leur propre ensemble d'autorisations sur des serveurs distants.
Exemple
L'exemple suivant montre comment créer un canal nommé à l'aide de la classe NamedPipeClientStream. Dans cet exemple, le processus serveur crée quatre threads. Chaque thread peut accepter une connexion cliente. Le processus client connecté fournit ensuite le serveur avec un nom de fichier. Si le client possède les autorisations suffisantes, le processus serveur ouvre le fichier et renvoie son contenu au client.
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
L'exemple suivant indique le processus client qui utilise la classe NamedPipeClientStream. Le client se connecte au processus serveur et envoie un nom de fichier au serveur. Le serveur renvoie ensuite le contenu du fichier au client. Le contenu du fichier est alors affiché dans la console.
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()
}
Programmation fiable
Comme les processus client et serveur sont, dans cet exemple, censés être exécutés sur le même ordinateur, le nom du serveur fourni à l'objet NamedPipeClientStream est "localhost". Si les processus client et serveur étaient sur des ordinateurs séparés, "localhost" serait alors remplacé par le nom de réseau de l'ordinateur qui exécute le processus serveur.
Voir aussi
Tâches
Comment : utiliser des canaux anonymes pour la communication entre processus locaux