2009-12-16 10 views
5

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

FileInputStream fileInputStream = new FileInputStream(file); 
OutputStream outputStream = socket.getOutputStream(); 
byte[] buf = new byte[BUFFER_SIZE]; 
int len = 0; 
while ((len = fileInputStream.read(buf)) > 0) { 
    outputStream.write(buf, 0, len); 
} 
outputStream.flush(); 
socket.close(); 

इस कोड को प्रत्येक जुड़े ग्राहक के लिए विशेष रूप से धागा में मार डाला गया है।

जब मैं छोटी फ़ाइलें (.htm, .gif, .swf, आदि) के साथ सौदा है, सब कुछ ठीक काम करता है (हालांकि, मैं कुछ भी ब्राउज़र में गलत दिखाई नहीं है)। लेकिन जब मैं बड़ी फाइलें (.iso) डाउनलोड करता हूं, विशेष रूप से कई फाइलें, जब सिस्टम लोड हो रहा है, कभी-कभी मुझे वास्तव में अजीब व्यवहार मिलता है। ब्राउज़र में 99.99% फ़ाइल डाउनलोड होती है और जब अनलोड किए गए बाइट्स के BUFFER_SIZE से कम होते हैं, तो कुछ सेकंड के लिए स्टॉप डाउनलोड करते हैं और फिर ब्राउज़र कहता है कि त्रुटि हुई है। मैं नहीं समझ सकता कि क्या होता है, क्योंकि सभी डेटा सफलतापूर्वक पढ़ा जाता है और यहां तक ​​कि सभी डेटा को सफलतापूर्वक outputStream लिखा है। जैसा कि आप देख सकते हैं, मैं फ्लश() भी करता हूं, लेकिन इसका कोई परिणाम नहीं होता है।

क्या कोई मुझे बता सकता है कि क्या होता है?

संपादित
अपलोड की गई परियोजना filehosting.org करने के लिए।
Download source files। स्रोत कोड, Build.xml और Readme.txt के साथ ज़िप संग्रह है। समाधान बनाने के लिए चींटी का प्रयोग करें। ClientManager.java में वर्णित समस्या होती है, आपको वहां एक टिप्पणी मिल जाएगी।

+0

हो सकता है कि हम कुछ अप्रासंगिक देखने की जरूरत है। –

+0

सत्य कहने के लिए, मैंने केवल लॉगिंग और इनलाइन विधि कॉल को हटा दिया है। – levanovd

+2

क्या आप अपने HTTP प्रतिक्रिया शीर्षकों में 'सामग्री-लंबाई' सेट कर रहे हैं? यदि हां, तो आप इसे किस पर सेट कर रहे हैं? –

उत्तर

1

सुनिश्चित नहीं है कि ऐसा क्यों होगा, मुझे आपके कोड में कोई समस्या नहीं दिखाई दे रही है। क्या आपने FileInputStream संलग्न करने के लिए BufferedInputStream का उपयोग करने का प्रयास किया है?

+0

समस्या FileInputStream में नहीं है, यदि डेटा स्रोत एक फ़ाइल नहीं है मैं एक ही समस्या है, लेकिन यह पुन: पेश करने के लिए कठिन है। यह भी डीबग दिखाता है कि सभी डेटा फ़ाइल से सफलतापूर्वक पढ़ा जाता है। – levanovd

1

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

आप जावा आप के लिए थोड़ी देर प्रतीक्षा करने के लिए पूछ सकते हैं,

socket.setOption(SocketOptions.SO_LINGER, new Integer(60)); 
+0

की कोशिश की socket.setSoLinger (सच, 60000); कोई प्रभाव नहीं। – levanovd

2

JDK 1.6 codebase के माध्यम से एक त्वरित ट्राउल के आधार पर:

  • socket.getOutputStream() रिटर्न एक SocketOutputStream उदाहरण
  • flush() वास्तव में एक पर एक SocketOutputStream उदाहरण
  • write() पर कोई प्रभाव नहीं SocketOutputStream उदाहरण जावा कोड
  • shutdownOutput() में कुछ भी बफ़र होना सुनिश्चित करना चाहिए कि किसी भी बकाया डेटा सॉकेट के उत्पादन की ओर नीचे बंद करने से पहले लिखा है प्रतीत नहीं होता। कम से कम, टिप्पणियां कहते हैं कि।

हालांकि, सॉकेट आदि कार्यान्वयन के कुछ देशी तरीकों है, और मुझे लगता है कि में तल्लीन नहीं किया।

मैं क्या बता सकते हैं के आधार पर, "सही" अनुक्रम होगा:

socket.shutdownOutput(); 
socket.close(); 

हालांकि, अगर आप कहते हैं कि तुम कि कोशिश की है। क्या यह संभव है कि दूसरे छोर पर आवेदन जल्दी ही टीसीपी/आईपी कनेक्शन बंद कर रहा है?

एक और सोचा: आप setSoLinger(true, 60000) कोशिश की, लेकिन 60000 सेकंड संभवतः अब ओएस अनुमति देता है। setSoLinger(true, 60) आज़माएं, और आउटपुट स्ट्रीम खोलने से पहले इसे करने का प्रयास करें।

+0

मुझे पहले भी यही समस्या थी। मैंने कभी शटडाउन आउटपुट की कोशिश नहीं की। मैं 5 रुपये शर्त लगाता हूं कि यह उसकी समस्या का समाधान करेगा। उस समय मैंने जो कोशिश की थी वह संदेश वापस प्राप्त करने पर कुछ वापस भेजना था - यह प्रोटोकॉल का हिस्सा था, इसलिए यह कोई बड़ी बात नहीं थी। –

+0

मुझे लगता है कि ओपी HTTP का उपयोग कर रहा है और इसलिए कोई अन्य संदेश जोड़ने का विकल्प नहीं है। –

+0

मैं कसम खाता हूं कि यह काम नहीं करता है। ठीक है, मैं आज अपनी सभी स्रोत फ़ाइलों को साझा करने का प्रयास करूंगा, शायद कोई समस्या उत्पन्न करेगा। – levanovd

0

मैं लंबाई पहले भेजकर और फिर इंतजार कर रहे करने के लिए इस्तेमाल कर रहा हूँ जब तक मैं प्राप्त है कि डेटा, लेकिन अगर आप ऐसा नहीं कर सकते, इस ब्लॉग उपयोगी होना चाहिए:

http://vadmyst.blogspot.com/2008/04/proper-way-to-close-tcp-socket.html

इस के लिए है। नेट, लेकिन मूल तर्क समान होना चाहिए।

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

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