2009-09-23 15 views
13

मैं जावा में एक गेम के लिए अपना स्वयं का कस्टम सर्वर सॉफ़्टवेयर बना रहा हूं (गेम और मूल सर्वर सॉफ़्टवेयर जावा के साथ लिखे गए थे)। कोई प्रोटोकॉल दस्तावेज उपलब्ध नहीं है, इसलिए मुझे वायरशर्क के साथ पैकेट पढ़ने होंगे।एक टीसीपी विंडो अपडेट क्या है?

जबकि कोई ग्राहक सर्वर को कनेक्ट कर रहा है, तो उसे Gzip प्रारूप में स्तर फ़ाइल भेजती है। स्तर भेजने में लगभग 9 4 पैकेट्स पर, मेरा सर्वर क्लाइंट को ArrayIndexOutOfBoundsException के साथ क्रैश करता है। मूल सर्वर से कैप्चर फ़ाइल के अनुसार, यह उस बिंदु पर एक टीसीपी विंडो अपडेट भेजता है। एक टीसीपी विंडो अपडेट क्या है, और मैं सॉकेट चैनेल का उपयोग करके एक कैसे भेजूं?

उत्तर

50

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

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

यह एक टीसीपी स्टॉल है। यह कई कारणों से हो सकता है, लेकिन आखिरकार इसका मतलब यह है कि प्रेषक रिसीवर पढ़ने से तेज़ी से संचार कर रहा है।

एक बार प्राप्त करने वाले अंत में ऐप सॉकेट से पढ़ने के लिए वापस आ जाता है, तो यह कुछ बफर किए गए डेटा को निकाल देगा, जो कुछ जगह मुक्त करता है।रिसीवर प्रेषक को यह बताने के लिए एक "विंडो अपडेट" पैकेट भेज देगा कि यह कितना डेटा संचारित कर सकता है। प्रेषक अपने buffered डेटा संचारित शुरू होता है और यातायात सामान्य रूप से प्रवाह करना चाहिए।

बेशक, यदि रिसीवर लगातार धीमा होता है तो आप बार-बार स्टालों प्राप्त कर सकते हैं।

मैंने यह लिखा है जैसे प्रेषक और रिसीवर अलग हैं, लेकिन हकीकत में, दोनों सहकर्मी प्रत्येक एसीके पैकेट के साथ विंडो अपडेट का आदान-प्रदान कर रहे हैं, और दोनों तरफ इसकी खिड़की भर सकती है।

समग्र संदेश यह है कि आपको सीधे विंडो अपडेट पैकेट भेजने की आवश्यकता नहीं है। वास्तव में एक को धोखा देना एक बुरा विचार होगा।

अपवाद के बारे में आप देख रहे हैं ... यह विंडो अद्यतन पैकेट द्वारा या तो होने या रोका जाने की संभावना नहीं है। हालांकि, यदि ग्राहक पर्याप्त तेज़ी से नहीं पढ़ रहा है, तो हो सकता है कि आप डेटा खो रहे हों। अपने सर्वर में, आपको अपने सॉकेट.write() कॉल से वापसी मान की जांच करनी चाहिए। यह उन बाइट्स की संख्या से कम हो सकता है जिन्हें आप लिखने की कोशिश कर रहे हैं। ऐसा तब होता है जब प्रेषक का प्रेषण बफर भरा हो जाता है, जो एक टीसीपी स्टॉल के दौरान हो सकता है। आप बाइट खो सकते हैं।

उदाहरण के लिए, यदि आप लिखने के लिए प्रत्येक कॉल के साथ 8192 बाइट लिखने की कोशिश कर रहे हैं, लेकिन कॉल में से एक 5691 लौटाता है, तो आपको अगली कॉल पर शेष 2501 बाइट्स भेजने की आवश्यकता है। अन्यथा, क्लाइंट उस 8K ब्लॉक के शेष को नहीं देख पाएगा और आपकी फ़ाइल सर्वर की तरफ से क्लाइंट साइड पर कम होगी।

+3

मेरी बग-फू मुझे बताती है कि यह अंतिम पैराग्राफ समस्या को दूर करने की संभावना है। – caf

+1

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

+0

+1! – Izza

7

यह टीसीपी/आईपी स्टैक में वास्तव में गहरा होता है; आपके एप्लिकेशन (सर्वर और क्लाइंट) में आपको टीसीपी विंडोज़ के बारे में चिंता करने की ज़रूरत नहीं है। त्रुटि कुछ और होना चाहिए।

2

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

+0

सहायता के लिए धन्यवाद। स्टैक ट्रेस बहुत उपयोगी नहीं है, क्योंकि क्लाइंट कोड obfuscated है इसलिए सभी वर्गों और विधियों एकल पत्र हैं ... अधिक शोध की जरूरत है! – phpscriptcoder

+0

@phpscriptcoder: शायद आपको मूल प्रोग्रामर निकाल दिया जाना चाहिए ... –

0

क्या आपको exception के साथ कोई details मिलता है?

यह संभावना टीसीपी विंडो अद्यतन पैकेट
से संबंधित नहीं है (यदि आप इसे कई उदाहरण के लिए वास्तव में दोहराने को देखा है?)

अधिक होने की संभावना अपने प्रसंस्करण कोड है कि प्राप्त डेटा पर काम करता है से संबंधित है।

0

यह आमतौर पर केवल एक ट्रिगर है, आपकी समस्या का कारण नहीं है।

उदाहरण के लिए, यदि आप एनआईओ चयनकर्ता का उपयोग करते हैं, तो एक विंडो अपडेट एक लेखन चैनल के जागने को ट्रिगर कर सकता है। यह बदले में आपके कोड में दोषपूर्ण तर्क को ट्रिगर करता है।

एक स्टैकट्रैक प्राप्त करें और यह आपको मूल कारण दिखाएगा।

2

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

https://wiki.wireshark.org/TCP_Analyze_Sequence_Numbers

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