7 Ağustos 2019

PipeStream

using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        /*
         
         PipeStream
         .Net 3.5 ile çıkmıştır. Bir işlemin diğer işlemlerle Windows pipes protokolü üzerinden haberleşmesini sağlar.

         İki çeşittir.
         * Anonymous pipe (daha hızlı)
            Aynı bilgisiyarda ki parnet ve child işlemleri için tek yönlü haberleşmesini sağlar.
         * Named pipe (daha esnek):
            Aynı bilgisayarda ki veya aynı Windows ağındaki farklı bilgisayarlar arasında ki keyfi işlemler arasında çift yönlü haberleşmesini sağlar.

        Bir tek bilgisayar üzerinde ki IPC(interprocess communication) haberleşme için pipe kullanmak uygundur.       

             */


        static void Main(string[] args)
        {
            //NamedPipeServerExample();
            AnonymousPipeServerExample();
            Console.ReadKey();
        }

        /*Named Pipes
         Named pipes ile taraflar aynı isim üzerinden doğrudan haberleşir. Protokol iki farklı rol tanımlar: Client ve Server
         Client ve Server arasında ki haberleşme aşağıdaki gibidir.
         NamedPipeServerStream ile server örneği oluşturulur ve WaitForConnection methodu çağrılır.
         NamedPipeClientStream ile client oluşturulur ve Connect ile bağlanılır.
         */

        static byte[] ReadMessage(PipeStream stream)
        {
            using (var ms = new MemoryStream())
            {
                var buffer = new Byte[0x1000]; // Read in 4KB blocks
                do
                {
                    ms.Write(buffer, 0, stream.Read(buffer, 0, buffer.Length));
                } while (!stream.IsMessageComplete);
                return ms.ToArray();
            }
        }

        static void NamedPipeServerExample()
        {
            string serverName = "pipedream";

            Task.Factory.StartNew(() =>
            {
                using (var server = new NamedPipeServerStream(serverName, PipeDirection.InOut, 1, PipeTransmissionMode.Message))
                {
                    server.WaitForConnection();
                    byte[] msg = Encoding.UTF8.GetBytes("Hello");
                    server.Write(msg, 0, msg.Length);
                    var resp = Encoding.UTF8.GetString(ReadMessage(server));
                    Console.WriteLine(resp);
                }
            });
            Task.Factory.StartNew(() =>
            {
                using (var client = new NamedPipeClientStream(serverName))
                {
                    client.Connect();
                    client.ReadMode = PipeTransmissionMode.Message;
                    var rec = Encoding.UTF8.GetString(ReadMessage(client));
                    Console.WriteLine(rec);
                    var msg = Encoding.UTF8.GetBytes("Hello right back!");
                    client.Write(msg, 0, msg.Length);
                }
            });
        }


        /*Anonymous pipes
         Anonymous pipe parent ve child arasında ki iki işlem arasında tek yönlü bir haberleşme sağlar.
         System çapıda isim kullanmak yerine doğrudan private handle üzerinden ayarlanır.

        1. Server AnonymousPipeServerStream örneği oluşturulur, PipeDirection In ve Out şeklinde belirtilir.
        2. Server GetClientHandleAsString ile pipe'ın kimliğini çağırırız k bunu clienta göndereceğiz.(Client oluşturulurken parametre olarak vereceğiz.)
        3. child process AnonymousPipeClientStream PipeDirection un karşıtı olarak girilir.
        4. server 2. adımda üretilen yerel handle i serbest bırakmak için DisposeLocalCopyOfClientHandle metodunu çağırırız.
        5. parent ve child processler birbirileri ile writing ve reading ile çalışır.
         */

        static void AnonymousPipeServerExample()
        {
            string clientExe = @"C:\Users\developer\Source\repos\ConsoleApp1\ClientDemo\bin\Debug\ClientDemo.exe";
            HandleInheritability inherit = HandleInheritability.Inheritable;
            using (var tx = new AnonymousPipeServerStream(PipeDirection.Out, inherit))
            using (var rx = new AnonymousPipeServerStream(PipeDirection.In, inherit))
            {
                string txID = tx.GetClientHandleAsString();
                string rxID = rx.GetClientHandleAsString();
                var startInfo = new ProcessStartInfo(clientExe, txID + " " + rxID);
                startInfo.UseShellExecute = false; // Required for child process
                Process p = Process.Start(startInfo);
                tx.DisposeLocalCopyOfClientHandle(); // Release unmanaged
                rx.DisposeLocalCopyOfClientHandle(); // handle resources.
                tx.WriteByte(100);
                Console.WriteLine("Server received: " + rx.ReadByte());
                p.WaitForExit();
            }
        }       
    }
}

///////////////
using System;
using System.IO.Pipes;

namespace ClientDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var rxID = args[0];
            var txID = args[1];
            using (var rx = new AnonymousPipeClientStream(PipeDirection.In, rxID))
            using (var tx = new AnonymousPipeClientStream(PipeDirection.Out, txID))
            {
                Console.WriteLine("Client received: " + rx.ReadByte());
                tx.WriteByte(200);
            }

        }
    }
}