Поделиться через


Практическое руководство. Использование анонимных каналов для локального взаимодействия между процессами

Анонимные каналы обеспечивают межпроцессное взаимодействие на локальном компьютере. Они предоставляют меньше возможностей, чем именованные каналы, но требуют меньше ресурсов. С помощью анонимных каналов вы можете легко организовать межпроцессное взаимодействие на локальном компьютере. Анонимные каналы не подходят для обмена данными по сети.

Для реализации анонимных каналов используются классы AnonymousPipeServerStream и AnonymousPipeClientStream.

Пример 1

В следующем примере показано, как отправить строку из родительского процесса в дочерний процесс через анонимные каналы. В этом примере создается AnonymousPipeServerStream объект в родительском процессе со значением PipeDirectionOut. Затем родительский процесс создает дочерний процесс с помощью дескриптора AnonymousPipeClientStream клиента для создания объекта. В дочернем процессе PipeDirection имеет значение In.

Теперь родительский процесс отправляет предоставленную пользователем строку в дочерний процесс. Эта строка выводится в консоль дочернего процесса.

Ниже представлен серверный процесс для этого примера.

#using <System.dll>
#using <System.Core.dll>

using namespace System;
using namespace System::IO;
using namespace System::IO::Pipes;
using namespace System::Diagnostics;

ref class PipeServer
{
public:
    static void Main()
    {
        Process^ pipeClient = gcnew Process();

        pipeClient->StartInfo->FileName = "pipeClient.exe";

        AnonymousPipeServerStream^ pipeServer =
            gcnew AnonymousPipeServerStream(PipeDirection::Out,
            HandleInheritability::Inheritable);

        Console::WriteLine("[SERVER] Current TransmissionMode: {0}.",
            pipeServer->TransmissionMode);

        // Pass the client process a handle to the server.
        pipeClient->StartInfo->Arguments =
            pipeServer->GetClientHandleAsString();
        pipeClient->StartInfo->UseShellExecute = false;
        pipeClient->Start();

        pipeServer->DisposeLocalCopyOfClientHandle();

        try
        {
            // Read user input and send that to the client process.
            StreamWriter^ sw = gcnew StreamWriter(pipeServer);

            sw->AutoFlush = true;
            // Send a 'sync message' and wait for client to receive it.
            sw->WriteLine("SYNC");
            pipeServer->WaitForPipeDrain();
            // Send the console input to the client process.
            Console::Write("[SERVER] Enter text: ");
            sw->WriteLine(Console::ReadLine());
            sw->Close();
        }
        // Catch the IOException that is raised if the pipe is broken
        // or disconnected.
        catch (IOException^ e)
        {
            Console::WriteLine("[SERVER] Error: {0}", e->Message);
        }
        pipeServer->Close();
        pipeClient->WaitForExit();
        pipeClient->Close();
        Console::WriteLine("[SERVER] Client quit. Server terminating.");
    }
};

int main()
{
    PipeServer::Main();
}
using System;
using System.IO;
using System.IO.Pipes;
using System.Diagnostics;

class PipeServer
{
    static void Main()
    {
        Process pipeClient = new Process();

        pipeClient.StartInfo.FileName = "pipeClient.exe";

        using (AnonymousPipeServerStream pipeServer =
            new AnonymousPipeServerStream(PipeDirection.Out,
            HandleInheritability.Inheritable))
        {
            Console.WriteLine("[SERVER] Current TransmissionMode: {0}.",
                pipeServer.TransmissionMode);

            // Pass the client process a handle to the server.
            pipeClient.StartInfo.Arguments =
                pipeServer.GetClientHandleAsString();
            pipeClient.StartInfo.UseShellExecute = false;
            pipeClient.Start();

            pipeServer.DisposeLocalCopyOfClientHandle();

            try
            {
                // Read user input and send that to the client process.
                using (StreamWriter sw = new StreamWriter(pipeServer))
                {
                    sw.AutoFlush = true;
                    // Send a 'sync message' and wait for client to receive it.
                    sw.WriteLine("SYNC");
                    pipeServer.WaitForPipeDrain();
                    // Send the console input to the client process.
                    Console.Write("[SERVER] Enter text: ");
                    sw.WriteLine(Console.ReadLine());
                }
            }
            // Catch the IOException that is raised if the pipe is broken
            // or disconnected.
            catch (IOException e)
            {
                Console.WriteLine("[SERVER] Error: {0}", e.Message);
            }
        }

        pipeClient.WaitForExit();
        pipeClient.Close();
        Console.WriteLine("[SERVER] Client quit. Server terminating.");
    }
}
Imports System.IO
Imports System.IO.Pipes
Imports System.Diagnostics

Class PipeServer
    Shared Sub Main()
        Dim pipeClient As New Process()

        pipeClient.StartInfo.FileName = "pipeClient.exe"

        Using pipeServer As New AnonymousPipeServerStream(PipeDirection.Out, _
            HandleInheritability.Inheritable)

            Console.WriteLine("[SERVER] Current TransmissionMode: {0}.",
                pipeServer.TransmissionMode)

            ' Pass the client process a handle to the server.
            pipeClient.StartInfo.Arguments = pipeServer.GetClientHandleAsString()
            pipeClient.StartInfo.UseShellExecute = false
            pipeClient.Start()

            pipeServer.DisposeLocalCopyOfClientHandle()

            Try
                ' Read user input and send that to the client process.
                Using sw As New StreamWriter(pipeServer)
                    sw.AutoFlush = true
                    ' Send a 'sync message' and wait for client to receive it.
                    sw.WriteLine("SYNC")
                    pipeServer.WaitForPipeDrain()
                    ' Send the console input to the client process.
                    Console.Write("[SERVER] Enter text: ")
                    sw.WriteLine(Console.ReadLine())
                End Using
            Catch e As IOException
                ' Catch the IOException that is raised if the pipe is broken
                ' or disconnected.
                Console.WriteLine("[SERVER] Error: {0}", e.Message)
            End Try
        End Using

        pipeClient.WaitForExit()
        pipeClient.Close()
        Console.WriteLine("[SERVER] Client quit. Server terminating.")
    End Sub
End Class

Пример 2

Ниже представлен клиентский процесс для этого примера. Серверный процесс запускает клиентский процесс и передает ему дескриптор клиента. Полученному исполняемому файлу в коде клиентского процесса следует присвоить имя pipeClient.exe и сохранить его в том же каталоге, где расположен исполняемый файл серверного процесса, прежде чем запускать серверный процесс.

#using <System.Core.dll>

using namespace System;
using namespace System::IO;
using namespace System::IO::Pipes;

ref class PipeClient
{
public:
    static void Main(array<String^>^ args)
    {
        if (args->Length > 1)
        {
            PipeStream^ pipeClient = gcnew AnonymousPipeClientStream(PipeDirection::In, args[1]);

            Console::WriteLine("[CLIENT] Current TransmissionMode: {0}.",
                pipeClient->TransmissionMode);

            StreamReader^ sr = gcnew StreamReader(pipeClient);

            // Display the read text to the console
            String^ temp;

            // Wait for 'sync message' from the server.
            do
            {
                Console::WriteLine("[CLIENT] Wait for sync...");
                temp = sr->ReadLine();
            }
            while (!temp->StartsWith("SYNC"));

            // Read the server data and echo to the console.
            while ((temp = sr->ReadLine()) != nullptr)
            {
                Console::WriteLine("[CLIENT] Echo: " + temp);
            }
            sr->Close();
            pipeClient->Close();
        }
        Console::Write("[CLIENT] Press Enter to continue...");
        Console::ReadLine();
    }
};

int main()
{
    array<String^>^ args = Environment::GetCommandLineArgs();
    PipeClient::Main(args);
}
using System;
using System.IO;
using System.IO.Pipes;

class PipeClient
{
    static void Main(string[] args)
    {
        if (args.Length > 0)
        {
            using (PipeStream pipeClient =
                new AnonymousPipeClientStream(PipeDirection.In, args[0]))
            {
                Console.WriteLine("[CLIENT] Current TransmissionMode: {0}.",
                   pipeClient.TransmissionMode);

                using (StreamReader sr = new StreamReader(pipeClient))
                {
                    // Display the read text to the console
                    string temp;

                    // Wait for 'sync message' from the server.
                    do
                    {
                        Console.WriteLine("[CLIENT] Wait for sync...");
                        temp = sr.ReadLine();
                    }
                    while (!temp.StartsWith("SYNC"));

                    // Read the server data and echo to the console.
                    while ((temp = sr.ReadLine()) != null)
                    {
                        Console.WriteLine("[CLIENT] Echo: " + temp);
                    }
                }
            }
        }
        Console.Write("[CLIENT] Press Enter to continue...");
        Console.ReadLine();
    }
}
Imports System.IO
Imports System.IO.Pipes

Class PipeClient
    Shared Sub Main(args() as String)
        If args.Length > 0 Then
            Using pipeClient As New AnonymousPipeClientStream(PipeDirection.In, args(0))
                Console.WriteLine("[CLIENT] Current TransmissionMode: {0}.", _
                   pipeClient.TransmissionMode)

                Using sr As New StreamReader(pipeClient)
                    ' Display the read text to the console
                    Dim temp As String

                    ' Wait for 'sync message' from the server.
                    Do
                        Console.WriteLine("[CLIENT] Wait for sync...")
                        temp = sr.ReadLine()
                    Loop While temp.StartsWith("SYNC") = False

                    ' Read the server data and echo to the console.
                    temp = sr.ReadLine()
                    While Not temp = Nothing
                        Console.WriteLine("[CLIENT] Echo: " + temp)
                        temp = sr.ReadLine()
                    End While
                End Using
            End Using
        End If
        Console.Write("[CLIENT] Press Enter to continue...")
        Console.ReadLine()
    End Sub
End Class

См. также