2011-07-15 16 views
7

सी # नामांकित पाइपसेवरस्ट्रीम का उपयोग करते समय, यदि कोई क्लाइंट कोई संदेश-अंत-पैटर्न नहीं भेजता है (जैसे \ r \ n जब सर्वर रीडलाइन() के साथ पढ़ता है) नामांकित पाइपसेवरस्ट्रीम रीड विधियां हमेशा के लिए प्रतीक्षा करेंगी और कोई गर्भपात नहीं करेगा() या इंटरप्ट() विधियां उस धागे पर काम करेंगी।नामित पाइप सर्वर पढ़ा गया टाइमआउट

के बाद से:
1) NamedPipeServerStream
2) बीच में बंद करें() या अंतरायन() के लिए समर्थित नहीं Stream.ReadTimeout धागा
3 पर काम नहीं करता) NamedPipeServerStream.Disconnect() निचले काम
यह स्पष्ट नहीं है , NamedPipeServerStream पढ़ने के संचालन पर टाइमआउट कैसे सेट करें?


मुझे एक उदाहरण पेश करने दें। आईपीसी के विनिर्देश के लिए हमें \ 0-समाप्त तारों के आदान-प्रदान की आवश्यकता है। एक ग्राहक संदेश भेजता है, सर्वर संदेश को संसाधित करता है और 'जरूरी' प्रतिक्रिया भेजता है। यदि ग्राहक अंत में \ 0 नहीं भेजता है (क्लाइंट हमारा नहीं है इसलिए हम इसके कामकाज की शुद्धता की गारंटी नहीं दे सकते हैं), रीड विधि हमेशा के लिए प्रतीक्षा करेगी और क्लाइंट (क्योंकि हम इसे नियंत्रित नहीं करते हैं) हमेशा के लिए प्रतीक्षा कर सकते हैं एक प्रतिक्रिया के लिए भी। पर NamedPipeServerStream संचालन पढ़

public void RestartServer() 
    { 
     _pipeServerThread.Interrupt(); //doesn't affect Read wait 
     _pipeServerThread.Abort();  //doesn't affect Read wait 
    } 

    private void PipeServerRun(object o) //runs on _pipeServerThread 
    { 
     _pipeServer = new NamedPipeServerStream(_pipeName, InOut, 100, 
         PipeTransmissionMode.Message, PipeOptions.WriteThrough); 
     //_pipeServer.ReadTimeout = 100; //System.InvalidOperationException: Timeouts are not supporte d on this stream. 

     // Wait for a client to connect 
     while (true) 
     { 
      _pipeServer.WaitForConnection(); 
      string request = ReadPipeString(); 
      //... process request, send response and disconnect 
     } 
    } 

    /// <summary> 
    /// Read a \0 terminated string from the pipe 
    /// </summary> 
    private string ReadPipeString() 
    { 
     StringBuilder builder = new StringBuilder(); 
     var streamReader = new StreamReader(_pipeServer); 

     while (true) 
     { 
      //read next byte 
      char[] chars = new char[1]; 
      streamReader.Read(chars, 0, 1); // <- This will wait forever if no \0 and no more data from client 

      if (chars[0] == '\0') return builder.ToString(); 
      builder.Append(chars[0]); 
     } 
    } 

तो समय समाप्ति सेट करने के लिए:

अगला एक कार्यान्वयन की एक सरल उदाहरण है?

उत्तर

2

आप संदेश मोड में पाइप चल रहे हैं के बाद से, आप पहली बार पूरे संदेश एक byte[] बफर या एक मेमोरी स्ट्रीम और में तो पढ़ना चाहिए तय है कि क्या यह वैध है और यह डिकोड। पाइप संदेशों की एक निश्चित लंबाई है। इसे स्पष्ट रूप से पुनर्प्राप्त नहीं किया जा सकता है, लेकिन यह तब दिखाई देता है जब आप किसी संदेश-मोड पाइप से पढ़ रहे होते हैं। Win32 ReadFile संदेश में अपठित बाइट्स होने पर ERROR_MORE_DATA के साथ विफल रहता है, तो यह संदेश इंगित करने के लिए TRUE देता है। इसके बाद, एक नया संदेश उपलब्ध होने तक ReadFile पर कॉल अवरुद्ध हो जाएगा। StreamReader स्वाभाविक रूप से इनमें से कोई भी नहीं जानता है और आपके धागे को अवरुद्ध करता है।

अद्यतन: टाइमआउट लागू करने के लिए, एसिंक्रोनस I/O (Stream.BeginRead) का उपयोग करें। StreamReader इसे सीधे समर्थन नहीं करता है। यदि आप पूरी तरह इसका इस्तेमाल करना आवश्यक है, एक आवरण धारा जो अंतर्निहित धारा और समर्थन समय समाप्ति पर BeginRead के मामले में Read को लागू करेगा, रद्द आदि

+0

धन्यवाद, लेकिन दुर्भाग्य से यह मेरे प्रश्न का उत्तर नहीं है। सी # नामांकित पाइपसेवरस्ट्रीम में IsMessageComplete ध्वज है, मुझे विश्वास है, ERROR_MORE_DATA कर्मचारियों पर निर्भर करता है। लेकिन यह संदेश के वास्तविक अंत से पहले सच होने के लिए होता है। यह पहली बार हम जांच में से एक था। यदि क्लाइंट TransactNamedPipe का उपयोग करता है जैसे यह काम करता है, लेकिन जब कोई C# नामांकित पाइप क्लाइंट का उपयोग करता है या WinApi में फ़ंक्शन लिखें - IsMessageComplete को वास्तविक संदेश को पूरा किया जा सकता है। मुझे लगता है कि यह एक बार फिर प्रेषक की स्ट्रीम प्रकृति की वजह से है। – MajesticRa

+0

हां, फिर भी यह संदेश मोड में पाइप क्यों चलाता है? संदेश मोड में, प्रत्येक Win32 'Write' कॉल के लिए एक पाइप संदेश बनाया जाता है। यदि आपके ग्राहक इस सम्मेलन का पालन नहीं कर रहे हैं, तो संदेश मोड व्यर्थ है। (वैसे, क्या क्लाइंट वास्तव में पाइप के क्लाइंट एंड को संदेश मोड में सेट करते हैं?) –

+1

दुर्भाग्य से दुनिया सही नहीं है और मेरे पास अभी विनिर्देश है। हमारा परीक्षण क्लाइंट संदेश मोड में है। लेकिन हम मौजूदा ग्राहकों के बारे में इसकी गारंटी नहीं दे सकते। ऐसा लगता है कि BeginRead के साथ भी कोई समस्या है, लेकिन मैं अभी भी इसके साथ प्रयोग करता हूं। – MajesticRa

1

बाइट के लिए NamedPipeServerStream.ReadMode और/या .TransmissionMode सेट करने का प्रयास लिखें। इनके बावजूद आपको NamedPipeServerStream के साथ उपलब्ध BeginRead/EndRead विधियों का उपयोग करना चाहिए। इस तरह आप टाइमआउट तर्क स्वयं को कार्यान्वित कर सकते हैं।

संबंधित मुद्दे