2012-05-13 12 views
9

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

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

प्रश्न अब मुझे सोचने के बाद है या नहीं, जावा सॉकेट का आउटपुटस्ट्रीम वास्तव में वह सामान कतार देता है जो वह स्वयं भेजना चाहता है, इस प्रकार पहले से ही एक कतार की आवश्यकता को खत्म कर देता है। गहन समस्याएं होने की संभावना तब होती है जब सर्वर तब तक अवरुद्ध हो जाता है जब तक कि उसे क्लाइंट से प्रतिक्रिया प्राप्त नहीं होती है कि प्रेषित ऑब्जेक्ट प्राप्त किया गया था।

धन्यवाद।

+0

यदि मैं थ्रेड के रन फ़ंक्शन में आउटपुट या इनपुट स्ट्रीम प्राप्त करने का प्रयास करता हूं तो मैंने एक समान समस्या में भाग लिया है।सॉकेट के ब्लॉकिंग (दोनों getInputStream, और getOutputStream) के लिए समस्या यह है क्योंकि यह रन फ़ंक्शन में है ... समाधान इसे कन्स्ट्रक्टर में रखना, चर को सहेजना और फिर चर में चर को संदर्भित करना प्रतीत होता है। – Zimm3r

उत्तर

4

बेशक, जब आप सॉकेट में लिखते हैं, तो यह लिखना buffered है। इस बफर आकार को सेट करने के लिए सॉकेट ऑब्जेक्ट में setSendBufferSize() विधि है। यदि आपका बफर इस बफर में कैश किया जा सकता है, तो निश्चित रूप से, आप तुरंत निम्न सॉकेट पर फिर से सक्रिय हो सकते हैं। अन्यथा इस बफर को तुरंत ग्राहक को फ़्लश करने की आवश्यकता है। तो, फ्लशिंग के दौरान आपको अवरुद्ध किया जा रहा है। यदि आप बफर को फ़्लश करते समय अवरुद्ध होने से बचना चाहते हैं, तो आपको गैर ब्लॉकिंग I/O में SocketChannel का उपयोग करना होगा। वैसे भी, कई सॉकेट को एक साथ लिखने का सबसे अच्छा विकल्प, प्रत्येक सॉकेट को एक अलग थ्रेड के साथ प्रबंधित करना है, ताकि सभी लिख एक ही समय में निष्पादित किए जा सकें।

+5

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

+0

भले ही टॉमसज़ की पोस्ट एक बेहतर उदाहरण थी, वही है जो मैं स्पष्टीकरण ईजेपी के संदर्भ में देख रहा था। आपका बहुत बहुत धन्यवाद। – salbeira

8

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

जावा में यह OutputStream पर लिखने के रूप में प्रकट होता है। अंतर्निहित टीसीपी/आईपी स्टैक/ऑपरेटिंग सिस्टम क्लाइंट को प्राप्त करने के लिए तैयार होने तक अधिक डेटा भेजने की अनुमति नहीं देता है।

आप आसानी से इसका परीक्षण कर सकते हैं!

final Socket client = new Socket("localhost", 4444); 
final OutputStream outputStream = client.getOutputStream(); 
int packet = 0; 
while(true) { 
    System.out.println(++packet); 
    outputStream.write(new byte[1024 * 4]); 
} 

ग्राहक लूप पर लटकी हुई है:

new Thread(new Runnable() { 
    @Override 
    public void run() { 
     try { 
      final ServerSocket serverSocket = new ServerSocket(4444); 
      final Socket clientSocket = serverSocket.accept(); 
      final InputStream inputStream = clientSocket.getInputStream(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    } 
}).start(); 

और एक साधारण ग्राहक कि सिर्फ 4K बैचों में के रूप में यह कर सकते हैं के रूप में ज्यादा डेटा भेजता है: मैं साधारण सर्वर है कि कनेक्शन स्वीकार करता है लेकिन आने वाले डेटा को पढ़ने के लिए विफल रहता है कार्यान्वित 95 पुनरावृत्तियों के बाद मेरा कंप्यूटर (आपका माइलेज भिन्न हो सकता है)। हालांकि अगर मैं सर्वर थ्रेड में inputStream से पढ़ता हूं - लूप चालू और चालू होता है।

+0

यदि मैं थ्रेड के रन फ़ंक्शन में आउटपुट या इनपुट स्ट्रीम प्राप्त करने का प्रयास करता हूं तो मैंने एक समान समस्या में भाग लिया है। सॉकेट के ब्लॉकिंग (दोनों getInputStream, और getOutputStream) के लिए समस्या यह है क्योंकि यह रन फ़ंक्शन में है ... समाधान इसे कन्स्ट्रक्टर में रखना, चर को सहेजना और फिर चर में चर को संदर्भित करना प्रतीत होता है। – Zimm3r

0

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

पढ़ने की तरफ, आप अवरुद्ध होने से बचने के लिए उपलब्ध() का उपयोग कर सकते हैं। लेखन पक्ष पर कोई मिलान कॉल मौजूद नहीं है। मेरी इच्छा थी कि वहां था।

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