दिलचस्प पोस्ट
TZInfo :: डेटासॉर्सनोटफ़ाउंड त्रुटि विंडोज़ पर रेल v4.1.0 सर्वर शुरू करने के लिए MySQL, एक क्वेरी के साथ कई तालिकाओं को अपडेट करें प्रतिबिंब का उपयोग करते हुए मैं एक सामान्य प्रकार की सही पाठ परिभाषा कैसे प्राप्त करूं? JQuery के उपयोग से सिंक्रनाइज़ किए गए स्क्रॉलिंग? फ़ाइलों को पढ़ने और लिखने का सबसे आसान तरीका .delay () और .setTimeout () SQL सर्वर में एक डीबीएफ फ़ाइल कैसे आयात करें मैट्रिक्स को 3-स्तंभ तालिका में परिवर्तित करें ('रिवर्स धुएं', 'अनपिवट', 'फ्लैटेन', 'सामान्य') मैं C ++ में एक फ़ाइल का आकार कैसे प्राप्त करूं? सूची दृश्य का उपयोग करना: हेडर दृश्य कैसे जोड़ें? एंड्रॉइड एमुलेटर में एपीके फ़ाइल कैसे स्थापित करें? क्रोम एक्सटेंशन में jQuery का उपयोग कैसे करें? किसी विशेष राशि के बाद `std :: cin` टाइमआउट से पढ़ने के लिए कैसे करें क्या UIWebView के लिए साझा किया गया एचटीटीपीकुकी स्टोरेज का मैन्युअल रूप से कुकी सेट करना संभव है? एक कस्टम तुलनित्र के साथ c ++ में प्राथमिकता_एक्यू को घोषित करता है

NetworkStream से .NET में पढ़ने का सही तरीका क्या है

मैं इसके साथ संघर्ष कर रहा हूं और मुझे कोई कारण नहीं मिल सकता है कि मेरा कोड एक टीसीपी सर्वर से ठीक से पढ़ने में नाकाम रहा है, मैंने भी लिखा है। मैं TcpClient क्लास और इसकी GetStream() विधि का उपयोग कर रहा हूँ लेकिन कुछ अपेक्षा के अनुरूप काम नहीं कर रहा है या तो ऑपरेशन ब्लॉक अनिश्चित काल तक (अंतिम पढ़ने वाला कार्य समय-समय पर अपेक्षित नहीं होता), या डेटा क्रॉप हो गया है (किसी कारण के लिए एक रीड ऑपरेशन 0 लौटाता है और पाश से बाहर निकलता है, संभवतः सर्वर तेज तेज़ी से प्रतिक्रिया नहीं दे रहा है)। ये इस कार्य को कार्यान्वित करने के तीन प्रयास हैं:

 // this will break from the loop without getting the entire 4804 bytes from the server string SendCmd(string cmd, string ip, int port) { var client = new TcpClient(ip, port); var data = Encoding.GetEncoding(1252).GetBytes(cmd); var stm = client.GetStream(); stm.Write(data, 0, data.Length); byte[] resp = new byte[2048]; var memStream = new MemoryStream(); int bytes = stm.Read(resp, 0, resp.Length); while (bytes > 0) { memStream.Write(resp, 0, bytes); bytes = 0; if (stm.DataAvailable) bytes = stm.Read(resp, 0, resp.Length); } return Encoding.GetEncoding(1252).GetString(memStream.ToArray()); } // this will block forever. It reads everything but freezes when data is exhausted string SendCmd(string cmd, string ip, int port) { var client = new TcpClient(ip, port); var data = Encoding.GetEncoding(1252).GetBytes(cmd); var stm = client.GetStream(); stm.Write(data, 0, data.Length); byte[] resp = new byte[2048]; var memStream = new MemoryStream(); int bytes = stm.Read(resp, 0, resp.Length); while (bytes > 0) { memStream.Write(resp, 0, bytes); bytes = stm.Read(resp, 0, resp.Length); } return Encoding.GetEncoding(1252).GetString(memStream.ToArray()); } // inserting a sleep inside the loop will make everything work perfectly string SendCmd(string cmd, string ip, int port) { var client = new TcpClient(ip, port); var data = Encoding.GetEncoding(1252).GetBytes(cmd); var stm = client.GetStream(); stm.Write(data, 0, data.Length); byte[] resp = new byte[2048]; var memStream = new MemoryStream(); int bytes = stm.Read(resp, 0, resp.Length); while (bytes > 0) { memStream.Write(resp, 0, bytes); Thread.Sleep(20); bytes = 0; if (stm.DataAvailable) bytes = stm.Read(resp, 0, resp.Length); } return Encoding.GetEncoding(1252).GetString(memStream.ToArray()); } 

आखिरी एक "काम करता है", लेकिन यह निश्चित रूप से बदसूरत दिखता है कि हार्ड कोडिंग नींद को पाश के अंदर रखकर विचार किया जा रहा है कि कुर्सियां ​​पहले से ही पढ़ने के समय का समर्थन करती हैं! क्या मुझे NetworkStream के TcpClient पर कुछ संपत्ति (एआईएस) सेटअप करने की आवश्यकता है? क्या समस्या सर्वर में रहती है? सर्वर कनेक्शन बंद नहीं करता है, ऐसा करने के लिए क्लाइंट पर निर्भर है। उपरोक्त UI थ्रेड संदर्भ (परीक्षण प्रोग्राम) के अंदर भी चल रहा है, हो सकता है कि उसके साथ कुछ करना है …

क्या कोई जान NetworkStream.Read कि NetworkStream.Read को ठीक से कैसे उपयोग किया जाए। डेटा को पढ़ने के लिए पढ़ें जब तक कोई और डेटा उपलब्ध नहीं हो? मुझे लगता है कि मैं क्या चाहता हूं, पुराने Win32 winsock टाइमआउट गुणों की तरह कुछ है … ReadTimeout , आदि। यह पढ़ने के लिए समय-समय पर पहुंचने की कोशिश करता है, और उसके बाद 0 लौटाता है … लेकिन कभी-कभी यह तब होता है जब डेटा उपलब्ध होना चाहिए (या रास्ते में .. क्या रिटर्न 0 पढ़ा सकता है यदि उपलब्ध है?) और यह तब तक अनिश्चित काल तक ब्लॉक होगा जब डेटा उपलब्ध नहीं है …

हाँ, मैं एक नुकसान में हूँ!

Solutions Collecting From Web of "NetworkStream से .NET में पढ़ने का सही तरीका क्या है"

नेटवर्किंग कोड लिखना, परीक्षण और डीबग करना बेहद कठिन है।

आपके पास कई तरह से विचार करने के लिए अक्सर ऐसा होता है जैसे:

  • जो डेटा को एक्सचेंज किया जाता है (इंटेल x86 / x64 थोड़ा-एंडियन पर आधारित है) के लिए आप "एन्डियन" का उपयोग करेंगे – बड़े-एन्डियन का इस्तेमाल करने वाले सिस्टम अभी भी छोटे-एंडियन (और इसके विपरीत) डेटा पढ़ सकते हैं, लेकिन वे को डेटा पुनर्व्यवस्थित करना होगा जब आपके "प्रोटोकॉल" का दस्तावेजीकरण करते हैं, तो यह स्पष्ट करता है कि आप किसका उपयोग कर रहे हैं

  • क्या कोई "सेटिंग्स" जो सॉकेट्स पर सेट की गई हैं जो "स्ट्रीम" के व्यवहार को प्रभावित कर सकती है (उदा। SO_LINGER) – यदि आपके कोड बहुत संवेदनशील हैं तो आपको कुछ लोगों को चालू या बंद करने की आवश्यकता हो सकती है

  • वास्तविक दुनिया में भीड़ कैसे होती है जो धारा में देरी का कारण बनती है आपके पढ़ने / लेखन तर्क को प्रभावित करती है

यदि क्लाइंट और सर्वर (या तो दिशा में) के बीच "संदेश" का आदान-प्रदान किया जाता है तो आकार में भिन्न हो सकता है, तो आपको उस "संदेश" को एक विश्वसनीय तरीके से (उर्फ प्रोटोकॉल) का आदान-प्रदान करने के लिए एक रणनीति का उपयोग करने की आवश्यकता होती है।

एक्सचेंज को संभालने के कई अलग-अलग तरीके हैं:

  • संदेश आकार से पहले आने वाले शीर्ष लेख में एन्कोड किया गया संदेश – यह पहले 2/4/8 बाइट्स (आपके अधिकतम संदेश आकार पर निर्भर) में "नंबर" हो सकता है, या अधिक विदेशी "हेडर" हो सकता है

  • वास्तविक डेटा के साथ "एन्कोडेड" मार्कर (प्रेजिनील) का एक विशेष "अंत" का उपयोग करें, यदि वास्तविक डेटा की संभावना को "मार्कर के अंत" के साथ भ्रमित किया गया हो तो एन्कोड किया गया / बच गया

  • एक टाइमआउट का उपयोग करें …. यानी कोई बाइट प्राप्त करने की कोई निश्चित अवधि का मतलब है कि संदेश के लिए कोई और डेटा नहीं है – हालांकि, यह कम समय-अवधि के साथ होने वाली त्रुटि हो सकती है, जो आसानी से भीड़भासी धाराओं पर हिट हो सकती है

  • अलग "कनेक्शन" पर एक "कमांड" और "डेटा" चैनल है …. यह एफ़टीपी प्रोटोकॉल का उपयोग करता है (इसका फायदा अलग से कनेक्शन के डेटा से अलग है … दूसरे कनेक्शन की कीमत पर)

प्रत्येक दृष्टिकोण में "शुद्धता" के लिए इसके पेशेवर और विपक्ष हैं

नीचे दिए गए कोड "टाइमआउट" विधि का उपयोग करता है, क्योंकि ऐसा लगता है कि आप चाहते हैं

http://msdn.microsoft.com/en-us/library/bk6w7hs8.aspx देखें। आप TCPClient पर NetworkStream तक पहुंच प्राप्त कर सकते हैं ताकि आप ReadTimeout को बदल सकें।

 string SendCmd(string cmd, string ip, int port) { var client = new TcpClient(ip, port); var data = Encoding.GetEncoding(1252).GetBytes(cmd); var stm = client.GetStream(); // Set a 250 millisecond timeout for reading (instead of Infinite the default) stm.ReadTimeout = 250; stm.Write(data, 0, data.Length); byte[] resp = new byte[2048]; var memStream = new MemoryStream(); int bytesread = stm.Read(resp, 0, resp.Length); while (bytesread > 0) { memStream.Write(resp, 0, bytesread); bytesread = stm.Read(resp, 0, resp.Length); } return Encoding.GetEncoding(1252).GetString(memStream.ToArray()); } 

इस लेखन नेटवर्क कोड पर अन्य रूपांतरों के लिए एक फुटनोट के रूप में … जब आप एक "ब्लॉक" से बचने के लिए Read चाहते हैं, तो आप DataAvailable ध्वज की जांच कर सकते हैं और फिर केवल बफ़र की जांच कर .Length हैं। .Length संपत्ति जैसे stm.Read(resp, 0, stm.Length);

अंतर्निहित सॉकेट ReceiveTimeout करना ReceiveTimeout प्रॉपर्टी ने चाल किया आप इसे इस तरह से एक्सेस कर सकते हैं: yourTcpClient.Client.ReceiveTimeout आप अधिक जानकारी के लिए दस्तावेज़ पढ़ सकते हैं

अब कोड केवल "सो" होगा जब तक कि कुछ डेटा सॉकेट में आने के लिए आवश्यक हो, या 20 एमबी से अधिक के लिए रीड ऑपरेशन की शुरुआत में, कोई डेटा नहीं होने पर यह अपवाद बढ़ाएगा। यदि आवश्यक हो तो मैं इस समयबाह्य को बदल सकता हूँ अब मैं प्रत्येक पुनरावृत्ति में 20ms की कीमत का भुगतान नहीं कर रहा हूँ, मैं इसे केवल पिछले पढ़ने के ऑपरेशन पर चुका रहा हूं। चूंकि मेरे पास सर्वर से पढ़ने वाले पहले बाइट्स में संदेश की सामग्री की लंबाई है, इसलिए मैं इसका इस्तेमाल इसे और भी अधिक करने के लिए कर सकता हूं और पढ़ने की कोशिश नहीं करता कि क्या सभी अपेक्षित आंकड़े पहले ही प्राप्त हुए हैं।

मुझे एसिंक्रोनस रीड को कार्यान्वित करने के लिए ReceiveTimeout का उपयोग करना बहुत आसान लगता है … यहां काम कोड है:

 string SendCmd(string cmd, string ip, int port) { var client = new TcpClient(ip, port); var data = Encoding.GetEncoding(1252).GetBytes(cmd); var stm = client.GetStream(); stm.Write(data, 0, data.Length); byte[] resp = new byte[2048]; var memStream = new MemoryStream(); var bytes = 0; client.Client.ReceiveTimeout = 20; do { try { bytes = stm.Read(resp, 0, resp.Length); memStream.Write(resp, 0, bytes); } catch (IOException ex) { // if the ReceiveTimeout is reached an IOException will be raised... // with an InnerException of type SocketException and ErrorCode 10060 var socketExept = ex.InnerException as SocketException; if (socketExept == null || socketExept.ErrorCode != 10060) // if it's not the "expected" exception, let's not hide the error throw ex; // if it is the receive timeout, then reading ended bytes = 0; } } while (bytes > 0); return Encoding.GetEncoding(1252).GetString(memStream.ToArray()); } 

आपकी आवश्यकता के अनुसार, Thread.Sleep पूरी तरह से ठीक है क्योंकि आप सुनिश्चित नहीं हैं कि डेटा कब उपलब्ध होगा ताकि आपको डेटा उपलब्ध होने का इंतजार करना पड़ सकता है मैंने आपके फ़ंक्शन के तर्क को थोड़ी-थोड़ी बदल दिया है, इससे आपको थोड़ी अधिक मदद मिल सकती है।

 string SendCmd(string cmd, string ip, int port) { var client = new TcpClient(ip, port); var data = Encoding.GetEncoding(1252).GetBytes(cmd); var stm = client.GetStream(); stm.Write(data, 0, data.Length); byte[] resp = new byte[2048]; var memStream = new MemoryStream(); int bytes = 0; do { bytes = 0; while (!stm.DataAvailable) Thread.Sleep(20); // some delay bytes = stm.Read(resp, 0, resp.Length); memStream.Write(resp, 0, bytes); } while (bytes > 0); return Encoding.GetEncoding(1252).GetString(memStream.ToArray()); } 

उम्मीद है की यह मदद करेगा!