Condividi tramite


Procedura: utilizzare le named pipe per la comunicazione tra processi in rete

Aggiornamento: novembre 2007

Le named pipe offrono maggiori funzionalità rispetto alle unnamed pipe. Tali funzionalità includono la comunicazione full duplex su rete e più istanze server; la comunicazione basata su messaggi e la rappresentazione client, che consente ai processi di connessione di utilizzare il proprio set di autorizzazioni sui server remoti.

Esempio

Nell'esempio seguente viene illustrato come creare una named pipe utilizzando la classe NamedPipeClientStream. In questo esempio, il processo server crea quattro thread. Ogni thread può accettare una connessione client. Il processo client connesso fornisce quindi un nome file al server. Se il client ha autorizzazioni sufficienti, il processo server apre il file e ne invia il contenuto nuovamente al 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

Nell'esempio che segue viene illustrato il processo client, che utilizza la classe NamedPipeClientStream. Il client si connette al processo server e invia un nome file al server. Il server invia il contenuto del file nuovamente al client. Il contenuto del file viene quindi visualizzato sulla 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()
}

Programmazione efficiente

Si presuppone che i processi client e server in questo esempio siano in esecuzione sullo stesso computer, pertanto il nome del server fornito all'oggetto NamedPipeClientStream è "localhost". Se i processi client e server fossero su computer separati, "localhost" verrebbe sostituito dal nome di rete del computer che esegue il processo server.

Vedere anche

Attività

Procedura: utilizzare le unnamed pipe per la comunicazione tra i processi locali

Concetti

Pipe