2012-10-25 23 views
9

मुझे सॉकेट में लिखने के दौरान बहुत अजीब व्यवहार है। अपने मोबाइल ग्राहक में मैं एक सॉकेट जो आरंभ नहीं हो जाता उपयोग कर रहा हूँ इस प्रकार है:आउटपुटस्ट्रीम.write() सफल लेकिन डेटा वितरित नहीं किया गया है

private void initSocket() 
{ 
    socket = new Socket(); 
    socket.connect(new InetSocketAddress(host, port)); 

    os = new DataOutputStream(socket.getOutputStream()); 
    is = new DataInputStream(socket.getInputStream()); 
} 

तो समय-समय पर (हर 60 सेकंड) मैंने पढ़ा है और इस सॉकेट के लिए कुछ डेटा लिखने (कोड यहाँ सरलीकृत एक छोटा सा है) :

if(!isSocketInitialized()) 
{ 
    initSocket(); 
} 

byte[] msg = getMessage(); 

os.write(msg); 
os.flush(); 

int bytesAvailable = is.available(); 
if(bytesAvailable>0) 
{ 
    byte[] inputBuffer = new byte[bytesAvailable]; 

    int numRead = is.read(inputBuffer, 0, bytesAvailable); 
    processServerReply(inputBuffer, numRead); 
} 

और यह काम करता है। लेकिन ... कभी-कभी (बहुत बार, शायद प्रति दिन 1 या 2 बार) मेरे सर्वर को डेटा प्राप्त नहीं होता है। मेरा ग्राहक लॉग इस तरह दिखता है:

Written A 
Written B 
Written C 
Written D 
Written E 

और इसी तरह। लेकिन सर्वर साइड पर ऐसा लगता है कि:

Received A 
Received E 

बी, सी, डी डेटा रिकॉर्ड, प्राप्त नहीं कर रहे थे तथ्य के बावजूद है कि ग्राहक पक्ष पर यह लग रहा है सभी डेटा की तरह किसी भी अपवाद के बिना भेजा गया था!

इस तरह के अंतराल छोटे (2-3 मिनट) हो सकते हैं जो बहुत खराब नहीं होते हैं, लेकिन कभी-कभी वे बहुत बड़े (1-2 घंटे = 60-120 चक्र) हो सकते हैं और यह वास्तव में मेरे ग्राहकों के लिए एक समस्या है।

मुझे वास्तव में कोई जानकारी नहीं है कि क्या गलत हो सकता है। डेटा क्लाइंट द्वारा भेजा जाता प्रतीत होता है, लेकिन यह सर्वर की तरफ कभी नहीं आता है। मैंने इसे प्रॉक्सी के साथ भी चेक किया है।

मेरे पास केवल लॉग हैं और मैं इस समस्या को पुन: उत्पन्न नहीं कर सकता (लेकिन यह मेरे ग्राहक के साथ हर बार एक बार होता है) और लॉग में कभी-कभी मुझे लगता है कि कनेक्शन अपवाद के साथ टूट गया है "प्रेषण विफल: ECONNRESET (हमउम्र द्वारा पुनःस्थापित संबंध)"। कि कार्यक्रम सॉकेट बंद कर देता है के बाद, यह reinitializes:

// close 
is.close(); 
os.close(); 
socket.close(); 

// reinitialize 
initSocket(); 

और जैसा कि ऊपर वर्णित फिर से डेटा लिखने के लिए कोशिश करता है। फिर मुझे समस्या दिखाई देती है: कनेक्शन स्थापित, सफल लेखन, लेकिन सर्वर पर कोई डेटा नहीं पहुंचा!

हो सकता है कि यह ECONNRESET के साथ कुछ करने के लिए हो, लेकिन मैं इसका उल्लेख करना चाहता हूं क्योंकि यह महत्वपूर्ण है।

मैं किसी भी विचार और सुझावों के लिए बहुत आभारी हूं।

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


यूपीडी: मैं इसे पुन: उत्पन्न कर सकता हूं! कम से कम आंशिक रूप से (क्लाइंट ए, बी, सी, डी, ई भेजता है और सर्वर केवल ए प्राप्त करता है)। यह हर बार अगर ऐसा होता:

  1. कनेक्शन स्थापित हो जाने, ग्राहक रीड और राईट -> ठीक

  2. कनेक्शन खो जाता है (मैं अपने WLAN रूटर :) बंद कर देते हैं), मैं IOException बन गया है, मैं धाराओं और सॉकेट को बंद करता हूं -> ठीक

  3. मैं अपना राउटर चालू करता हूं, कनेक्शन वापस आ गया है, मैं सॉकेट को फिर से शुरू करता हूं, प्रोग्राम अपवादों के बिना लिखता है(), लेकिन सर्वर पर कोई डेटा नहीं आता है ।

कनेक्शन वापस फिर से उपलब्ध है BTW के बाद से() 0.

+0

एक चीज जो मदद कर सकती है वह एक सर्वर होगा जो डिवाइस के साथ सिंक करने का प्रयास कर सकता है। यदि यह पहली बार डेटा को याद करता है, तो यह हमेशा कोशिश कर सकता है - इस पर निर्भर करता है कि आप कितनी बार डेटा के लिए मतदान करते हैं। – Max

+0

@ मैक्स, यकीन है, आप सही हैं। लेकिन सर्वर बंद सॉफ्टवेयर है और मैं प्रोटोकॉल नहीं बदल सकता। – Valelik

+0

क्या आप 'ByteArrayOutputStream' का उपयोग नहीं कर सके? कुछ [इस तरह] (http://stackoverflow.com/a/2984550/1134705) – jnthnjns

उत्तर

0

इस अजीब व्यवहार का कारण सर्वर की ओर एक बंद सॉकेट नहीं था। मैं इसे छोटे ग्राहक और सर्वर के साथ पुन: पेश कर सकता हूं। दोनों कोड की लाइनें, जो निम्न कार्य की जोड़ी से मिलकर बनता है:

  1. सर्वर
  2. एक मरे हुए स्थान अनुकरण करने के लिए कनेक्ट (जैसे अपने वाईफ़ाई बंद कर देते हैं)
  3. क्लाइंट की तरफ सॉकेट बंद
  4. अपने वाईफ़ाई
  5. पर
  6. बारी सर्वर साइड पर सॉकेट बंद नहीं करते इस संबंध के लिए ग्राहक से एक नया कनेक्शन
  7. लिखने डेटा स्थापित

वोला! ग्राहक बिना किसी त्रुटि के डेटा लिखता है, लेकिन सर्वर इसे प्राप्त नहीं करता है ...

लेकिन यदि सर्वर सॉकेट को भी बंद कर देता है, तो सर्वर इस डेटा को पढ़ सकता है। तो सर्वर सर्वर पर एक टाइमआउट के बाद सॉकेट को बंद करना चाहिए।

दुर्भाग्य से मेरे मामले में यह व्यवहार्य नहीं है, क्योंकि सर्वर एक मालिकाना तृतीय पक्ष सॉफ़्टवेयर है।

+2

तो सर्वर के साथ कुछ गंभीरता से गलत है। मूल कनेक्शन पर इसे पढ़ने के लिए समय या हमेशा के लिए ब्लॉक करना चाहिए या एक ईओएस प्राप्त करना चाहिए जो इसे उस कनेक्शन को बंद कर देता है; और इसे नए कनेक्शन से सफलतापूर्वक नए डेटा को पढ़ना चाहिए। यदि ऐसा नहीं होता है, तो यह सिंगल-थ्रेडेड है या इसमें कुछ अन्य समरूपता समस्या है। मैं नहीं देखता कि आपने इसे अपने प्रश्न के उत्तर के रूप में स्वीकार क्यों किया है जब यह इसका उत्तर नहीं देता है, केवल उस त्रुटि स्थिति को स्पष्ट करता है जिसमें यह होता है। कोई जवाब नहीं – EJP

2

available() परीक्षण से छुटकारा हमेशा देता है। यदि सहकर्मी उत्तर देने का अनुमान लगाता है, तो बस इसे पढ़ें। अन्यथा कभी-कभी आप जवाब पढ़ रहे होंगे और कभी-कभी आप नहीं करेंगे, और आप सिंक से बाहर हो जाएंगे। available() के बहुत कम सही उपयोग हैं, और यह उनमें से एक नहीं है।

+0

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

+0

@ वैलेलिक चुनिंदा प्रतिक्रिया के अनुसार चुनना कि यह कितना तेज़ हो सकता है, संभवतः सही नहीं हो सकता है, है ना? अब आप जो कर रहे हैं, वह हर तरह की समस्या काल्पनिक होगा, 'गायब डेटा' से, जिसे आपने अभी नहीं पढ़ा है, ब्लॉक लिखने के लिए, 'सहकर्मी द्वारा कनेक्शन रीसेट' करने के लिए। हमें बताएं कि जब आपने कोशिश की तो क्या हुआ। – EJP

+0

मैंने फिर से अपना संचार दोबारा लिखा है। और अब मेरे पास पढ़ने के लिए एक अतिरिक्त धागा है। तो मैं अब 'उपलब्ध()' का उपयोग नहीं करता हूं। लेकिन यह मदद नहीं की। मेरी भी यही समस्या है। – Valelik

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