2010-02-16 12 views
7

कल्पना कीजिए कि आप और मैं टीसीपी के माध्यम से काफी लंबी वाक्य (कहें, 1024000 बाइट्स) भेज रहे हैं।क्या मुझे डेटा आकार की जानकारी को टीसीपी हस्तांतरण में मैन्युअल रूप से एम्बेड करना चाहिए?

आप मेरे लिए एक 1,024,000 बाइट्स वाक्य लिखने हैं, तो आप वास्तव में NetworkStream का उपयोग में उन बाइट्स लिखने के लिए।

जब मैं प्राप्त करते हैं, मैं पहले से वाक्य के आकार को पता होना चाहिए कि आप भेजा?

यदि नहीं, तो मैं कैसे जांच सकता हूं कि मुझे स्ट्रीम को कब रोकना चाहिए। पढ़ना?

यदि हां, तो क्या प्रोग्राम में ऐसी सुविधाएं होनी चाहिए जो डेटा के डेटा में डेटा आकार एम्बेड करें? तो मुझे यह देखने के लिए पहले 4 बाइट प्राप्त होते हैं कि मुझे कितने कुल पढ़ना चाहिए?

क्या नेट में स्थानांतरण के डेटा आकार को स्वचालित रूप से एम्बेड करने के लिए कुछ भी है?

+0

ठीक है, क्या कोई मुझे बता सकता है कि धारा के अंत में न्यूल कैसे जोड़ना है? – Jack

उत्तर

4

न तो .NET और न ही टीसीपी प्रोटोकॉल में पहले से आने वाले संदेश के आकार को परिभाषित करने के लिए कुछ भी बनाया गया है। टीसीपी प्रोटोकॉल केवल निर्दिष्ट करता है कि सभी डेटा प्राप्त करने वाले अंत बिंदु पर स्थानांतरित किए जाएंगे (या कम से कम यह करने के लिए सबसे अच्छा प्रयास नियोजित किया जाएगा)।

रिसीवर को यह जानने के लिए कि आप कितना डेटा पढ़ना चाहते हैं, परिभाषित करने के लिए आप पूरी तरह उत्तरदायी हैं। आप यह कैसे करते हैं इसका विवरण - जैसा कि दूसरों ने इंगित किया है - जो आप स्थानांतरित कर रहे हैं उसकी प्रकृति पर निर्भर करते हैं: आप पहले की तरह लंबाई को भेज सकते हैं, आप टर्मिनर नामक विशेष अनुक्रमों को एन्कोड कर सकते हैं, आप पूर्वनिर्धारित डेटा खंडों का उपयोग कर सकते हैं इसलिए सभी संदेशों का एक ही आकार है, आदि

संपादित

यह एक टिप्पणी के रूप में बाहर शुरू किया, लेकिन वहाँ फिट कि सीमित कर की तुलना में यह करने के लिए अधिक है। धारा को

में जोड़े शून्य बस एक चरित्र है जो बाइनरी मान 0 (नहीं चरित्र 0 साथ भ्रमित होने की) है जोड़कर मतलब है। आपके स्थानांतरण के लिए उपयोग किए जा रहे एन्कोडिंग के आधार पर (यानी एएससीआईआई, यूटीएफ -8, यूटीएफ -16 इत्यादि) जो एक या एक से अधिक 0 बाइट भेजने में अनुवाद कर सकते हैं लेकिन यदि आप उचित अनुवाद का उपयोग कर रहे हैं तो आपको बस \0 जैसे कुछ डालना होगा आपकी स्ट्रिंग में ऊपर के सभी

string textToSend = "This is a NULL Terminated text\0"; 
byte[] bufferToSend = Encoding.UTF8Encoding.GetBytes(textToSend); 
बेशक

जाने वाले डेटा को भेज रहे हैं किसी भी अन्य NULLs शामिल नहीं है के बाकी के सभी मान लिया गया है: यहाँ एक उदाहरण है। इसका मतलब है कि यह पाठ है, और मनमाना बाइनरी डेटा नहीं (जैसे फ़ाइल की सामग्री)। यह बहुत महत्वपूर्ण है! अन्यथा आप संदेश टर्मिनेटर के रूप में NULL का उपयोग नहीं कर सकते हैं और आपको एक और योजना के साथ आना होगा।

+0

क्या आप कृपया मुझे बता सकते हैं कि स्ट्रीम के अंत में न्यूल कैसे जोड़ें? – Jack

+0

हां। एनीदर रास्ता डालें, एक टीसीपी सॉकेट ऑक्टेट्स की एक विश्वसनीय धारा प्रदान करता है। भेजने और प्राप्त करने के आवेदनों द्वारा किसी भी संरचना या सीमाओं को लगाया जाना चाहिए। –

+0

इसका नुकसान यह है कि यदि आप संदेश के अंत से परे पढ़ने से बचना चाहते हैं तो आप हमेशा स्ट्रीम से एक एकल बाइट का अनुरोध कर सकते हैं। यह बहुत धीमी हो सकती है। – x4u

1

जब मुझे प्राप्त होता है, तो क्या मुझे आपके द्वारा भेजे गए वाक्य के आकार के बारे में पहले पता होना चाहिए?

यह सहायक हो सकता है (प्रगति सलाखों को प्रस्तुत करने जैसी चीजों के लिए), लेकिन यह आवश्यक नहीं है।

यदि नहीं, तो मैं कैसे जांच सकता हूं कि मुझे स्ट्रीम को कब रोकना चाहिए। पढ़ना?

आपकी स्ट्रीम की सामग्री इसे परिभाषित करती है। उदाहरण के लिए, कई संदेश कुछ जानकारी एन्कोड करते हैं जो आपको बताते हैं कि यह संदेश खत्म हो गया है (उदाहरण के लिए, एक स्ट्रिंग के अंत का प्रतिनिधित्व करने के लिए एक शून्य बाइट, या </html> HTML दस्तावेज़ के अंत का प्रतिनिधित्व करने के लिए)।

1

आप इसे दो तरीकों से कर सकते हैं, एक तरीका है जिसे आपने वर्णित किया है - हेडर में संदेश का आकार रखना - और दूसरा स्ट्रीम पर किसी प्रकार का टर्मिनल मार्कर डालना है। उदाहरण के लिए, यदि आपके संदेश की गारंटी है कि NUL वर्णों को एम्बेड न किया जाए, तो आप NUL से समाप्त कर सकते हैं।

0

चूंकि टीसीपी एक विश्वसनीय प्रोटोकॉल है, इसलिए आप या तो बाइट्स की संख्या को इंगित करने या ट्रांसमिशन के अंत को इंगित करने के लिए कुछ प्रकार के टर्मिनेटर का उपयोग करने के लिए अपने प्रोटोकॉल को बना सकते हैं। यदि आप यूडीपी का उपयोग कर रहे थे, जो विश्वसनीय होने की गारंटी नहीं है, तो यह प्रोटोकॉल बनाने के लिए और अधिक महत्वपूर्ण होगा जो बाइट्स को रोक देगा या इंगित करेगा कि कितने बाइट्स की उम्मीद है (और एक पुन: ट्रांसमिशन तंत्र है) क्योंकि पैकेट समाप्त होने वाला पैकेट खो जा सकता है अधिकतम डेटा ट्रांसमिशन समय और टाइमआउट भी उपयोगी हो सकते हैं, लेकिन केवल तभी आप उचित अधिकतम निर्धारित कर सकते हैं।

1

यदि आप संदेश की कुल लंबाई को आसानी से जानते हैं या आसानी से पता लगा सकते हैं, तो मैं इसे पहले से प्रेषित करने का सुझाव दूंगा। यदि यह निर्धारित करने के लिए असंभव या बहुत महंगा है तो आप HTTP में chunked transfer encoding के समान कुछ उपयोग कर सकते हैं।

2

आम तौर पर, एक स्थायी चरित्र की तुलना में डेटा आकार के साथ शीर्षलेख का उपयोग करना बेहतर होता है। समाप्ति चरित्र विधि सेवा हमले से इनकार करने के लिए अतिसंवेदनशील है। मैं केवल आपकी सेवा में डेटा भेजना जारी रख सकता हूं, और जब तक मैं टर्मिनेटर शामिल नहीं करता, तब तक आपको क्रैश होने तक प्रोसेसिंग (और संभावित रूप से स्मृति आवंटित) रखने की आवश्यकता होती है।

कुल आकार वाले हेडर का उपयोग करना, यदि आपके लिए ट्रांसमिशन बहुत बड़ा है, तो आप इसे अनदेखा कर सकते हैं, या एक त्रुटि वापस भेज सकते हैं। यदि कोई दुर्भावनापूर्ण पार्टी शीर्षलेख में घोषित की गई तुलना में अधिक डेटा भेजने का प्रयास करती है, तो आपको अगली स्ट्रीम की शुरुआत में भ्रष्ट शीर्षलेख दिखाई देगा और इसे अनदेखा कर दिया जाएगा।

+0

अच्छी बात समझाने के लिए .. लेकिन यह रिसीवर के एक निष्पक्ष कार्यान्वयन को मानता है। आप कुछ सीमाओं को प्राप्त कर सकते हैं - और यह होना चाहिए कि आपको कितना डेटा प्राप्त होता है और प्रक्रिया को नियंत्रित किया जा सकता है जिसे सामान्य रूप से डेटा के सामान्य आकार के आधार पर निर्धारित किया जा सकता है जिसे एप्लिकेशन आमतौर पर अपेक्षा करता है –

1

मुख्य बिंदु यह है कि टीसीपी के साथ रिसीवर पक्ष पर सॉकेट की संख्या/आकार के साथ ट्रांसमिशन पक्ष पर सॉकेट लिखने की संख्या और आकार के बीच कोई पत्राचार नहीं होता है।

यदि डेटा की स्ट्रीम में कुछ प्रकार की संरचना है तो आपको पेलोड के चारों ओर किसी प्रकार का मेटा/रैपर डेटा जोड़ना होगा।

एक) एक जादुई संख्या का उपयोग आरंभ या अंत अपने डेटा संदेश के (या दोनों)

ख इंगित करने के लिए) का उपयोग करें:

कभी भी मुझे लगता है मैं के कुछ संयोजन का इस्तेमाल किया है इस समस्या को हल करने के लिए पड़ा है सामग्री को सत्यापित करने के लिए संदेश के अंत में एक चेकसम सही है (मुझे पता है कि टीसीपी & रीट्रानमिशन त्रुटि जांचने में त्रुटि करता है लेकिन चेकसम इस मामले में उपयोगी है जहां रिसीवर प्रारंभ/अंत जादू संख्या/अनुक्रम की आकस्मिक घटना को उठाता है धारा)

सी) प्रारंभिक जादू संख्या के बाद लंबाई क्षेत्र का उपयोग करें (बशर्ते संचारण पक्ष डेटा की लंबाई से पहले प्रसारण शुरू होता है जानता है)

Hoever जा रहा diy क्या उच्च स्तर प्रोटोकॉल libs आप उपयोग कर रहे भाषा/मंच के लिए लागू किया जाता है अच्छी तरह से देखने से पहले। NetworkStream? क्या विंडोज एपीआई/एमएफसी या कुछ है।

उदाहरण के लिए मुझे हाल ही में क्लाइंट/सर्वर सिस्टम स्थापित करना पड़ा।क्लाइंट & सर्वर कार्यक्षमता पहले से ही पाइथन में लिखी गई थी, इसलिए केवल पाइथन xmlrpclib/सर्वर का उपयोग करके दोनों प्रोग्रामों को एक साथ जोड़ना पूरी तरह से आसान हो गया - सचमुच उदाहरण की प्रतिलिपि बनाएँ और मैं 30 मिनट में किया गया था। अगर मैं खुद को टीसीपी पर सीधे कुछ मेकअप-अप प्रोटोकॉल को कोडित करता तो यह 5 दिन होता!

0

मेरा उत्तर नहीं होगा। विशेष रूप से बड़े डेटा सेट के लिए। इसका कारण यह है कि आकार भेजने से पहले आपके सिस्टम में विलंबता जोड़ती है।

यदि आप पहले आकार भेजना चाहते हैं, तो आपको इसे भेजने से पहले पूरे उत्तर की गणना करने की आवश्यकता है।

दूसरी तरफ, यदि आप टर्मिनेशन मार्कर का उपयोग करते हैं, तो आप निम्न डेटा की गणना करते समय डेटा के पहले बिट्स को जल्द से जल्द भेजना शुरू कर सकते हैं।

0

आप बाइनरी रीडर/बाइनरीवाइटर कक्षाओं की जांच भी कर सकते हैं जिन्हें किसी भी स्ट्रीम, टीसीपी या अन्यथा लपेटा जा सकता है।

स्ट्रिंग की लंबाई सहित देखभाल करने के दौरान अन्य कार्यों के बीच, स्ट्रिंग्स (अपनी पसंद के एन्कोडिंग में) पढ़ने/लिखने के लिए ये समर्थन भी।

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

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