【C#】解析C#中管道流的使用


目錄結構:

contents structure [+]

管道為進程間通信提供了一種可能。管道分為兩種,一種是匿名管道,另一種是命名管道。

1.匿名管道(anonymous pipe)

匿名管道,匿名管道只提供在本地電腦進程間的通信。匿名管道比命名管道花費的開銷更少,但提供的服務也比命名管道的少。匿名管道是單向的,而且不能用於網絡通信。匿名管道只支持單服務器實例。

匿名管道不支持消息傳輸模式(PipeTransmissionMode.Message),僅支持字節傳輸模式(PipeTransmissionMode.Byte)。

創建匿名管道需要使用AnonymousPipeClientStream和AnonymousPipeServerStream類,下面的案例展示了匿名的管道的用法。
首先創建一個PipeServer.cs文件,其內容如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PipeServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Process pipeClient1=new Process();
            pipeClient1.StartInfo.FileName = @"PipeClient.exe";
                        
            //AnonymousPipeServerStream is an one-way pipe. in other words it's only support PipeDirection.In or PipeDirection.Out.
            //in this program, we use PipeDirection.Out for send data to clients.
            using (AnonymousPipeServerStream pipeServer = 
                new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable)) {

                //send the client handle that from AnonymousPipeServerStream to client
                pipeClient1.StartInfo.Arguments = pipeServer.GetClientHandleAsString();
                pipeClient1.StartInfo.UseShellExecute = false;
                pipeClient1.Start();
                
                //closes the local copy of the AnonymousPipeClientStream object's handle
                //this method must be call after the client handle has been passed to the client
                //if this method isn't called, then the AnonymousPipeServerStream will not receive notice when client dispose of it's PipeStream object
                pipeServer.DisposeLocalCopyOfClientHandle();

                try
                {
                    using(StreamWriter sw=new StreamWriter(pipeServer)){
                        //automatic flush
                        sw.AutoFlush = true;
                        
                        sw.WriteLine("SYNC");
                        //it'll block util the other end of pipe has been read all send bytes
                        pipeServer.WaitForPipeDrain();
                        
                        String temp=null;
                        while(true){
                            temp=Console.ReadLine();
                            //send message to pipeclient from console
                            sw.WriteLine(temp);
                            //it'll block util the other end of pipe has been read all send bytes
                            pipeServer.WaitForPipeDrain();
                            if(temp=="exit"){
                                break;
                            }
                        }
                    }
                }
                catch (IOException e) {
                    Console.WriteLine("[server] exception:{0}",e.Message);
                }
            }
            
            pipeClient1.WaitForExit();
            pipeClient1.Close();
        
        }
    }
}
PipeServer.cs

然后創建PipeClient.cs文件,內容如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

    class Program
    {
        static void Main(string[] args)
        {
            
            using (PipeStream pipeClient = new AnonymousPipeClientStream(PipeDirection.In, args[0])) {

                using (StreamReader sr = new StreamReader(pipeClient)) {
                    String temp = null;
                    Console.WriteLine("[client] wait for sync ...");
                    do{
                        temp = sr.ReadLine();
                    }while(!temp.StartsWith("SYNC"));
                    Console.WriteLine("client in");
                    while ((temp = sr.ReadLine()) != null)
                    {
                        Console.WriteLine("[client] receive message: " + temp);
                        if(temp=="exit"){
                            break;
                        }
                    }
                }
                Console.Write("[client] Press Enter to exist...");
                Console.ReadLine();
            }
        }
    }
PipeClient.cs


這里只展示一個服務端一個客戶端,但實際中可以有多個客戶端。PipeClient.cs和PipeServer.cs應該在同一個文件夾下面,具體的路徑由PipeServer.cs中加載客戶端的路徑決定,本例中是在同一路徑下。然后可以使用csc將其都編譯為可執行文件。

2.命名管道(named pipe)

命名管道和匿名管道的功能相似,但他們有如下兩點區別:

  • 命名管道既可以支持直接傳輸模式(PipeTransmissionMode.Byte),也可以支持消息傳輸模式(PipeTransmissionMode.Message)
  • 命名管道既可以用於本地進程間的通信,也可以用於網絡通信。


創建命名管道需要使用NamedPipeServerStream和NamedPipeClientStream類,下面的案例展示了命名管道的用法:
PipeServer.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PipeServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Waiting client to connect...\n");

            using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut))
            {

                //wait client to connect
                pipeServer.WaitForConnection();

                Console.WriteLine("[server] a client connected");

                StreamReader reader = new StreamReader(pipeServer);
                StreamWriter writer = new StreamWriter(pipeServer);
                writer.AutoFlush = true;

                String line = null;
                while ((line = reader.ReadLine()) != null)
                {
                    Console.WriteLine("[server] receive message:"+line);

                    writer.WriteLine("I'm fine");

                    pipeServer.WaitForPipeDrain();

                    if ("line" == "EXIT")
                    {
                        break;
                    }
                }
            };

            Console.ReadLine();
        }
    }
}
PipeServer.cs

PipeClient.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PipeClient
{
    class Program
    {
        static void Main(string[] args)
        {
            //initialize NamePipeClientStream with serverName,pipeName,pipeDirection
            using (NamedPipeClientStream pipeClient =
            new NamedPipeClientStream("host path", "testpipe", PipeDirection.InOut)) {

                Console.WriteLine("[client] Attemping to connect to pipe...");
                pipeClient.Connect();

                Console.WriteLine("[client] connected to pipe");
                Console.WriteLine("[client] There are currently {0} pipe server instances open.",pipeClient.NumberOfServerInstances);

                StreamWriter writer = new StreamWriter(pipeClient);
                writer.AutoFlush = true;
                StreamReader reader = new StreamReader(pipeClient);

                String temp = "";
                while (true) {
                    temp = Console.ReadLine();

                    //send to server
                    writer.WriteLine(temp);

                    pipeClient.WaitForPipeDrain();

                    //read from server
                    Console.WriteLine("[client] read message from server:"+reader.ReadLine());

                    if (temp == "EXIT") {
                        break;
                    }
                }
            }

            Console.ReadLine();
        }
    }
}
PipeClient.cs

 

這里需要注意,"."代表本機地址。如果需要到其他服務器,替換就好了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM