C# – Giao tiếp giữa các process bằng Pipe Stream (Inter-process communication)

Kể từ .Net 3.5, bạn có thể dễ dàng thực hiện được việc truyền dữ liệu giữa các process (tiến trình) bằng các kênh Pipe, nhờ vào namespace mới System.IO.Pipes. Tùy theo mục đích, bạn có thể sử dụng loại Anonymous pipe hay Named pipe.

Giới thiệu

Trong lập trình, khái niệm Pipe có thể được hiểu một luồng có chức năng truyền tải dữ liệu giữa các processs. Pipe được chia thành hai loại:
Anonymous Pipe: cho phép giao tiếp trong máy tính cục bộ. Loại pipe này sử dụng ít thời gian xử lý hơn Named Pipe nhưng ít chức năng hơn. Anonymous Pipe chỉ truyền tài được một chiều, không sử dụng được thông qua mạng và thường dùng để tạo kênh giao tiếp giữa các thread hay giữa các process cha/con.
Named Pipe: hoạt động theo mô hình server/client. Named Pipe hỗ trợ giao tiếp hai chiều và có thể hoạt động thông qua mạng.

Sử dụng Named Pipe

Sử dụng các PipeStream khá đơn giản, trong bài này tôi chỉ tạo một ví dụ sử dụng Named Pipe. Bạn cần tạo hai đối tượng server và client với hai lớp khác nhau.
Server: Tạo một thể hiện của lớp NamedPipeServerStream và gọi phương thức WaiForConnection() để đợi kết nối từ client.
Client: Tạo một thể hiện của lớp NamedPipeClientStream và gọi phương thức Connect() để kết nối tới server.

Như tên của loại pipe này, cả server và client phải sử dụng cùng một chuỗi tên gọi để có thể kết nối được với nhau.

Tạo Server:

using System;
using System.IO.Pipes;

class PipeServer
{

    static void Main()
    {
        using (var s = new NamedPipeServerStream("FooPipe",PipeDirection.InOut))
        {
            s.WaitForConnection();

            // convert the message to byte array
            var data = GetBytes("Hello! Welcome to FooPipe Server!");
            // send data to clients
            s.Write(data,0,data.Length);
        }

        Console.Read();
    }

    static byte[] GetBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }

}

Tạo Client:

using System;
using System.IO.Pipes;

class PipeClient
{
    static void Main(string[] args)
    {
        using (var stream = new NamedPipeClientStream("FooPipe"))
        {
            stream.Connect();

            var buffer = new byte[1000];
            // read received data into buffer
            stream.Read(buffer,0,1000);

            Console.WriteLine(GetString(buffer));
        }

        Console.Read();
    }

    static string GetString(byte[] bytes)
    {
        char[] chars = new char[bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }
}

Chạy server trước, sau khi chạy client, bạn sẽ thấy thông điệp “Hello! Welcome to FooPipe Server!” hiển thị trên cửa sổ client.

Note: Ví dụ trên sử dụng cùng một máy để chạy nên client không cần xác định tên server. Nếu server đặt ở máy khác, bạn cần phải xác định tên server như sau:

… new NamedPipeClientStream(serverName, “FooPipe”);

Bạn có thể tìm hiểu thêm các ví dụ tại các link sau (MSDN):
 How to: Use Anonymous Pipes for Local Interprocess Communication
 How to: Use Named Pipes for Network Interprocess Communication