नामित पाइपों का उदाहरण


131

मैं कैसे काम करने के लिए एक साधारण - नंगे न्यूनतम लिखने की आवश्यकता है - परीक्षण आवेदन जो दिखाता है कि आईपीसी / नामांकित पाइप्स का उपयोग कैसे करें?

उदाहरण के लिए, कोई एक कंसोल एप्लिकेशन कैसे लिखेगा जहां प्रोग्राम 1 कहता है कि "हैलो वर्ल्ड" टू प्रोग्राम 2 और प्रोग्राम 2 को संदेश मिलता है और प्रोग्राम 1 को "रोजर दैट" का जवाब दिया जाता है।

जवाबों:


166
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            StartServer();
            Task.Delay(1000).Wait();


            //Client
            var client = new NamedPipeClientStream("PipesOfPiece");
            client.Connect();
            StreamReader reader = new StreamReader(client);
            StreamWriter writer = new StreamWriter(client);

            while (true)
            {
                string input = Console.ReadLine();
                if (String.IsNullOrEmpty(input)) break;
                writer.WriteLine(input);
                writer.Flush();
                Console.WriteLine(reader.ReadLine());
            }
        }

        static void StartServer()
        {
            Task.Factory.StartNew(() =>
            {
                var server = new NamedPipeServerStream("PipesOfPiece");
                server.WaitForConnection();
                StreamReader reader = new StreamReader(server);
                StreamWriter writer = new StreamWriter(server);
                while (true)
                {
                    var line = reader.ReadLine();
                    writer.WriteLine(String.Join("", line.Reverse()));
                    writer.Flush();
                }
            });
        }
    }
}

1
@JordanTrainor क्षमा करें, यह .net 4.5 में है। आप उपयोग कर सकते हैंThread.Sleep
LB

2
@Gusdor मैं कुछ सिंक-प्रिमाइट्स का उपयोग कर सकता था। लेकिन इसे पढ़ना अधिक कठिन होगा। मुझे लगता है कि यह नामांकित पाइप्स का उपयोग करने के बारे में एक विचार देने के लिए पर्याप्त है
LB

2
यदि आपको समस्या है कि पाइप एक बार पढ़ने के बाद बंद हो जाता है, तो इस उत्तर को देखें: stackoverflow.com/a/895656/941764
jgillich

11
आप .NET 4.5 का उपयोग कर रहे हैं, तो आप कर सकते हैं की जगह Task.Factory.StartNewके साथTask.Run
रुडी

2
क्या आपको reader/ का निपटान करना है writer? यदि हां, तो क्या आप उनमें से केवल एक का निपटान करते हैं? मैंने कभी ऐसा उदाहरण नहीं देखा, जहां दोनों एक ही धारा से जुड़े हों।
जोशवर्ति

21

किसी व्यक्ति के लिए जो IPC और नामांकित पाइप्स के लिए नया है, मैंने निम्न NuGet पैकेज को एक बड़ी मदद के रूप में पाया।

GitHub: .NET 4.0 के लिए नामांकित पाइप आवरण

पैकेज स्थापित करने के लिए पहले उपयोग करने के लिए:

PS> Install-Package NamedPipeWrapper

फिर एक उदाहरण सर्वर (लिंक से कॉपी किया गया):

var server = new NamedPipeServer<SomeClass>("MyServerPipe");
server.ClientConnected += delegate(NamedPipeConnection<SomeClass> conn)
    {
        Console.WriteLine("Client {0} is now connected!", conn.Id);
        conn.PushMessage(new SomeClass { Text: "Welcome!" });
    };

server.ClientMessage += delegate(NamedPipeConnection<SomeClass> conn, SomeClass message)
    {
        Console.WriteLine("Client {0} says: {1}", conn.Id, message.Text);
    };

server.Start();

उदाहरण ग्राहक:

var client = new NamedPipeClient<SomeClass>("MyServerPipe");
client.ServerMessage += delegate(NamedPipeConnection<SomeClass> conn, SomeClass message)
    {
        Console.WriteLine("Server says: {0}", message.Text);
    };

client.Start();

मेरे लिए इसके बारे में सबसे अच्छी बात यह है कि यहां स्वीकृत उत्तर के विपरीत यह एकल सर्वर से बात करने वाले कई ग्राहकों का समर्थन करता है।


5
मैं उत्पादन के लिए इस NuGet पैकेज की सिफारिश नहीं करेंगे। मैंने इसे लागू किया है और इसमें कुछ कीड़े हैं, मुख्य रूप से वास्तव में यह पता नहीं चल पाने के कारण कि पाइप के दूसरे छोर में एक संदेश पूरी तरह से प्राप्त हो गया है (टूटे हुए कनेक्शन की ओर जाता है, या कनेक्शन बहुत जल्द समाप्त हो जाता है) (कोड की जांच करें) github अगर आपको मुझ पर भरोसा नहीं है, तो "WaitForPipeDrain" को तब नहीं बुलाया जाता है जब इसे होना चाहिए), साथ ही आपके पास कई ग्राहक होंगे जब केवल एक ही सुन रहा हो क्योंकि ... बहुत सारे मुद्दे)। यह दुखद है क्योंकि इसका उपयोग करना वास्तव में आसान था। मुझे कम विकल्पों के साथ खरोंच से एक का पुनर्निर्माण करना पड़ा।
माइक्रो फ़ेलिक्स

हाँ अच्छी बात है, दुर्भाग्य से कि मूल अनुरक्षक ने वर्षों से परियोजना को अद्यतन नहीं किया है, सौभाग्य से यद्यपि कई कांटे मौजूद हैं जिनमें से अधिकांश आपके द्वारा चर्चा की गई समस्याओं को ठीक करते हैं।
मार्टिन लुककैन 16

2
@MartinLaukkanen: हैलो, मैं NamedPipeWrapper का उपयोग करने की योजना बना रहा हूं, आप जानते हैं कि कौन सा कांटा इस बग को ठीक कर रहा है? धन्यवाद
Whiletrue

17

आप वास्तव में एक नामित पाइप को इसके नाम, btw का उपयोग करके लिख सकते हैं।

डिफॉल्ट "एक्सेस से वंचित" त्रुटि के आसपास पाने के लिए एक कमांड शेल को प्रशासक के रूप में खोलें:

echo Hello > \\.\pipe\PipeName

3

लिनक्स पर FYI डॉटनेट कोर नेमपाइप्स का समर्थन नहीं करता है, यदि आप लिनक्स पर हैं तो इसके बजाय tcplistener की कोशिश करें

इस कोड में एक क्लाइंट राउंड ट्रिप एक बाइट है।

  • क्लाइंट बाइट लिखता है
  • सर्वर बाइट पढ़ता है
  • सर्वर बाइट लिखता है
  • ग्राहक बाइट पढ़ता है

डॉटनेट कोर 2.0 सर्वर कंसोल

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

namespace Server
{
    class Program
    {
        static void Main(string[] args)
        {
            var server = new NamedPipeServerStream("A", PipeDirection.InOut);
            server.WaitForConnection();

            for (int i =0; i < 10000; i++)
            {
                var b = new byte[1];
                server.Read(b, 0, 1); 
                Console.WriteLine("Read Byte:" + b[0]);
                server.Write(b, 0, 1);
            }
        }
    }
}

डॉटनेट कोर 2.0 क्लाइंट कंसोल

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

namespace Client
{
    class Program
    {
        public static int threadcounter = 1;
        public static NamedPipeClientStream client;

        static void Main(string[] args)
        {
            client = new NamedPipeClientStream(".", "A", PipeDirection.InOut, PipeOptions.Asynchronous);
            client.Connect();

            var t1 = new System.Threading.Thread(StartSend);
            var t2 = new System.Threading.Thread(StartSend);

            t1.Start();
            t2.Start(); 
        }

        public static void StartSend()
        {
            int thisThread = threadcounter;
            threadcounter++;

            StartReadingAsync(client);

            for (int i = 0; i < 10000; i++)
            {
                var buf = new byte[1];
                buf[0] = (byte)i;
                client.WriteAsync(buf, 0, 1);

                Console.WriteLine($@"Thread{thisThread} Wrote: {buf[0]}");
            }
        }

        public static async Task StartReadingAsync(NamedPipeClientStream pipe)
        {
            var bufferLength = 1; 
            byte[] pBuffer = new byte[bufferLength];

            await pipe.ReadAsync(pBuffer, 0, bufferLength).ContinueWith(async c =>
            {
                Console.WriteLine($@"read data {pBuffer[0]}");
                await StartReadingAsync(pipe); // read the next data <-- 
            });
        }
    }
}

2 प्रक्रियाओं के लिए इस तरह नामित पाइपों का उपयोग करना मुझे System Unauthorized Accesss Exception - path is denied
उत्तेजित

नहीं यकीन है कि शायद व्यवस्थापक के रूप में चला?
पैट्रिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.