Java.net। सॉकेट को कैसे ठीक करें: अपवाद: टूटा हुआ पाइप?


150

मैं अपाचे कॉमन्स http क्लाइंट का उपयोग कर रहा हूं ताकि पोस्ट पैरामीटर का उपयोग करके पोस्ट को पैरामीटर पोस्ट किया जा सके और यह नीचे की त्रुटि को शायद ही कभी फेंक रहा है।

java.net.SocketException: Broken pipe
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
        at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
        at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
        at org.apache.commons.httpclient.methods.ByteArrayRequestEntity.writeRequest(ByteArrayRequestEntity.java:90)
        at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
        at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
        at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
        at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)

क्या कोई यह बता सकता है कि इस अपवाद का कारण क्या है और इसे कैसे डीबग करना है?


1
इस कोशिश करने के लिए सबसे अच्छा है stackoverflow.com/questions/10142409/...
Vimalkumar नटराजन

जवाबों:


81

इसके कारण होता है:

  • आमतौर पर, जब दूसरे छोर ने पहले ही इसे बंद कर दिया है, तो एक कनेक्शन पर लिखना;
  • कम आमतौर पर, सहकर्मी सभी डेटा को पढ़े बिना कनेक्शन को बंद कर देता है जो पहले से ही उसके अंत में लंबित है।

तो दोनों ही मामलों में आपके पास एक खराब परिभाषित या लागू प्रोटोकॉल है।

एक तीसरा कारण है कि मैं यहां दस्तावेज नहीं दूंगा लेकिन जिसमें सहकर्मी द्वारा कनेक्शन को ठीक से बंद करने के बजाय जानबूझकर कार्रवाई करना शामिल है।


4
क्या आप कृपया इसे पहचानने और ठीक करने में मेरी मदद कर सकते हैं? मूल रूप से, कारण और पुष्टि कैसे करें?

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

26
यदि सर्वर साइड HTTP एप्लिकेशन को ब्रोकन पाइप अपवाद मिल रहा है, तो इसका मतलब है कि क्लाइंट ब्राउज़र दूसरे पेज पर / से बाहर निकल गया है / इतिहास में / जो भी हो गया है। बस इसके बारे में भूल जाओ।
लोर्न

3
हमने इस अपवाद को तब देखा है जब ब्राउज़र (उपयोग XMLHttpRequest.abort()) में अजाक्स अनुरोध को निरस्त कर रहा है ।
जेक

2
एक संभावित कारण एक प्रॉक्सी या Http सर्वर होगा जो कनेक्शन को बहुत जल्दी बंद कर देगा। उदाहरण के लिए, आपके J2EE सर्वर और एप्लिकेशन क्लाइंट के बीच एक अपाचे Http सर्वर, एक लघु परिभाषित टाइमआउट के साथ। कम से कम हमारे उत्पादन पर्यावरण पर ऐसा ही हुआ। पृष्ठों के बारे में ग्राहकों की शिकायत पूरी तरह से भरी हुई नहीं है, हमने JBoss लॉग पर इस त्रुटियों को देखा। कुछ परीक्षण के बाद हम देखते हैं कि समस्या एक खराब तरीके से कॉन्फ़िगर किया गया Http सर्वर था।
रिकार्डो विला

32

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

JVM के लिए उपलब्ध मेमोरी बढ़ाने की कोशिश करें या उन त्रुटियों के होने पर मेमोरी उपयोग की निगरानी करें।


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

2
स्पष्ट रूप से कम मेमोरी ने एप्लिकेशन को प्राप्त सॉकेट को बंद करने या वास्तव में एक ही प्रभाव के साथ पूरी तरह से बाहर निकलने का कारण बना। कम मेमोरी अपने आप टूटी हुई पाइप का कारण नहीं बनती है।
लोर्ने

1
यह वास्तव में हमारे भारी-भार के आवेदन के दौरान भी एक मुद्दा प्रतीत होता है
रुबेन डे व्रीस

7

सॉकेटएक्स अपवाद: टूटा हुआ पाइप, 'दूसरे छोर' (क्लाइंट या सर्वर) के कारण कनेक्शन को बंद कर देता है, जबकि आपका कोड या तो कनेक्शन से पढ़ रहा है या लिख ​​रहा है।

यह क्लाइंट / सर्वर एप्लिकेशन में एक बहुत ही सामान्य अपवाद है जो एप्लिकेशन नियंत्रण के बाहर क्लाइंट या सर्वर से ट्रैफ़िक प्राप्त करता है। उदाहरण के लिए, क्लाइंट एक ब्राउज़र है। यदि ब्राउज़र एक अजाक्स कॉल करता है, और / या उपयोगकर्ता केवल पृष्ठ या ब्राउज़र को बंद कर देता है, तो यह प्रभावी रूप से सभी संचार को अप्रत्याशित रूप से मार सकता है। मूल रूप से, आप किसी भी समय इस त्रुटि को देखेंगे, जब दूसरा छोर उनके आवेदन को समाप्त कर देगा, और आप इसका अनुमान नहीं लगा रहे थे।

यदि आप अपने आवेदन में इस अपवाद का अनुभव करते हैं, तो इसका मतलब है कि आपको अपना कोड जांचना चाहिए जहां IO (इनपुट / आउटपुट) होता है और इस IOException को पकड़ने के लिए एक कोशिश / कैच ब्लॉक के साथ लपेटें। फिर, यह तय करना है कि आप इस अर्ध-मान्य स्थिति को कैसे संभालना चाहते हैं।

आपके मामले में, आपके पास अभी भी जिस स्थान पर नियंत्रण है, वह कॉल है HttpMethodDirector.executeWithRetry- इसलिए सुनिश्चित करें कि कॉल कोशिश / कैच ब्लॉक के साथ लिपटी है, और इसे संभालें कि आप कैसे फिट देखते हैं।

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


यह सहकर्मी द्वारा कनेक्शन को बंद करने के कारण नहीं है, जबकि आप इसे पढ़ रहे हैं। यह एक अलग, धारा का अंत, स्थिति का कारण बनता है, जो अक्सर एक अपवाद नहीं होता है।
लोर्ने

5

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

इससे पहले:

OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Some text");
bw.close();
out.close();

उपरांत:

OutputStream os = urlConnection.getOutputStream();
OutputStream out = new BufferedOutputStream(os);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("Some text");
bw.close();
out.close();
os.close(); // This is a must.

8
यह वास्तव में बहुत अजीब है, क्योंकि BufferedOutputStreamहमेशा close()अपने अंतर्निहित आउटपुट स्ट्रीम (इस प्रकार आउटपुट स्ट्रीम urlConnection) पर कॉल करता है । Docs.oracle.com/javase/6/docs/api/java/io/…… और docs.oracle.com/javase/6/docs/api/java/io/…/ देखें, तो जब आपको कॉल आए तो os.close()इसे पहले ही बंद कर दिया जाना चाहिए । नहीं?
ओबेक

4
'os.close ()' 'a' नहीं है। उस मामले के लिए न तो 'out.close ()' है। 'bw.close ()' पर्याप्त है। @obedker सही है। यह परिवर्तन अकेले समस्या को ठीक नहीं कर सकता है।
लोर्ने का

1

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


इस त्रुटि को हल करने के लिए आपको बंद सॉकेट्स का उपयोग करने से बचने की कोशिश करनी होगी।
लोर्ने का

3
जबरदस्त हंसी। आप एसओ पर सभी फर्जी सलाह को सही करने में पूरा दिन बर्बाद कर सकते हैं।
डेव

2
@Dave से अलग। मैं कभी कभी करता हूं।
लोर्न

1

जब मैं एक साधारण जावा एप्लिकेशन विकसित कर रहा था, तो मैं एक ही समस्या थी जो एक विशिष्ट टीसीपी पर सुनता है। आमतौर पर, मुझे कोई समस्या नहीं थी, लेकिन जब मैंने कुछ तनाव परीक्षण चलाया तो मैंने देखा कि कुछ कनेक्शन त्रुटि के साथ टूट गया socket write exception

जांच के बाद मुझे एक समाधान मिला जो मेरी समस्या को हल करता है। मुझे पता है कि यह सवाल काफी पुराना है, लेकिन मैं अपना समाधान साझा करना पसंद करता हूं, कोई इसे उपयोगी पा सकता है।

सर्वर सर्वर निर्माण पर समस्या थी। मैंने जावदॉक से पढ़ा कि 50 लंबित सॉकेट्स की डिफ़ॉल्ट सीमा है। यदि आप दूसरा कनेक्शन खोलने का प्रयास करते हैं, तो इन्हें अस्वीकार कर दिया जाएगा। समाधान सर्वर साइड में इस डिफ़ॉल्ट कॉन्फ़िगरेशन को बदलने के लिए होता है। निम्नलिखित मामले में, मैं एक सॉकेट सर्वर बनाता हूं जो टीसीपी पोर्ट को सुनता है 10_000और अधिकतम 200लंबित सॉकेट स्वीकार करता है ।

new Thread(() -> {
      try (ServerSocket serverSocket = new ServerSocket(10_000, 200)) {
        logger.info("Server starts listening on TCP port {}", port);

        while (true) {
          try {
            ClientHandler clientHandler = clientHandlerProvider.getObject(serverSocket.accept(), this);
            executor.execute(clientHandler::start);
          } catch (Exception e) {
            logger.error(e.getMessage());
          }
        }

      } catch (IOException | SecurityException | IllegalArgumentException e) {
        logger.error("Could not open server on TCP port {}. Reason: {}", port, e.getMessage());
      }
    }).start();

ServerSocket के Javadoc से :

आने वाले कनेक्शन संकेतों (कनेक्ट करने का अनुरोध) के लिए अधिकतम कतार की लंबाई बैकलॉग पैरामीटर पर सेट है। यदि एक कनेक्शन संकेत आता है जब कतार भर जाती है, तो कनेक्शन से इनकार कर दिया जाता है।


0

मुद्दा यह हो सकता है कि आपकी तैनात की गई फाइलें सही RMI विधियों के साथ अपडेट न हों। यह देखने के लिए जांचें कि आपके RMI इंटरफ़ेस में पैरामीटर अपडेट किए गए हैं, या आपके ग्राहक के पास डेटा संरचनाएँ अपडेट नहीं हैं। या कि आपके RMI क्लाइंट का कोई पैरामीटर नहीं है जो आपके सर्वर संस्करण से भिन्न है।

यह सिर्फ एक शिक्षित अनुमान है। मेरे सर्वर एप्लिकेशन की क्लास फ़ाइलों को फिर से तैनात करने और फिर से परीक्षण करने के बाद, "ब्रोकन पाइप" की समस्या दूर हो गई।


RMI विधियाँ क्या हैं ? प्रश्न में RMI का उल्लेख नहीं किया गया है।
लोर्ने

0

उपरोक्त उत्तर इसका कारण बताते हैं java.net.SocketException: Broken pipe: दूसरे छोर ने कनेक्शन बंद कर दिया। जब मैंने इसका सामना किया तो मैं अनुभव साझा करना चाहूंगा:

  1. क्लाइंट के अनुरोध में, Content-Typeहेडर गलती से अनुरोध बॉडी से बड़ा सेट है वास्तव में है (वास्तव में कोई शरीर नहीं था)
  2. टोमैट सॉकेट में नीचे की सेवा उस आकार के डेटा का इंतजार कर रही थी (http टीसीपी पर है जो एनकैप्सुलेटिंग और ... द्वारा डिलीवरी सुनिश्चित करता है)
  3. जब 60 सेकंड की समय-सीमा समाप्त हो जाती है, तो टॉमकैट अपवाद को बाहर फेंक देता है: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception java.net.SocketTimeoutException: null
  4. क्लाइंट को टाइमआउट अपवाद के कारण स्थिति कोड 500 के साथ प्रतिक्रिया मिलती है।
  5. क्लाइंट क्लोज कनेक्शन (क्योंकि यह प्रतिक्रिया प्राप्त करता है)।
  6. टॉमकैट फेंकता है java.net.SocketException: Broken pipeक्योंकि क्लाइंट ने इसे बंद कर दिया है।

कभी-कभी, टॉमकैट टूटी हुई पाइप अपवाद को नहीं फेंकता है, क्योंकि टाइमआउट अपवाद कनेक्शन को बंद कर देता है, ऐसा अंतर मुझे भी भ्रमित कर रहा है।


Content-Typeहैडर एक संख्या नहीं बताता, तो यह किसी भी चीज से 'बड़ा' नहीं हो सकता। टाइमआउट अपवाद सॉकेट बंद न करें। उत्तर कोई मायने नहीं रखता है।
लोर्ने

@ ईजेपी शायद यह सामग्री की लंबाई थी, याद नहीं है। मुझे लगता है कि टॉमकैट में टाइमआउट इसे 500 वापस कर देता है, जबकि ग्राहक इस प्रतिक्रिया को प्राप्त करता है और कनेक्शन बंद कर देता है, जिसके कारण आखिरकार टॉमकैट को पर्याप्त बाइट्स प्राप्त नहीं होता है क्योंकि यह उम्मीद करता है।
टीना जूल

यदि टॉमकैट 500 भेजता है तो उसे पहले से ही वह सब कुछ प्राप्त हो जाता है जिसकी उसे योजना है। फिर भी कोई मतलब नहीं है।
लोर्ने

@ user207421 वास्तव में नहीं। टॉमकैट 500 भेजता है क्योंकि यह सभी अपेक्षाओं को प्राप्त नहीं करता है, लेकिन समयबद्ध है।
टीना

-1

JavaDoc:

आने वाले कनेक्शन संकेतों (कनेक्ट करने के लिए एक अनुरोध) के लिए अधिकतम कतार की लंबाई 50 पर सेट है। यदि कोई कनेक्शन संकेत कतार में भरा हुआ है, तो कनेक्शन से इनकार कर दिया जाता है।

आपको अपने सर्वर सॉकेट के "बैकलॉग" पैरामीटर को बढ़ाना चाहिए, उदाहरण के लिए

int backlogSize = 50 ;
new ServerSocket(port, backlogSize);

1
बैकलॉग बढ़ाने से 'टूटी हुई पाइप' त्रुटि हल नहीं होगी।
को लोर्ने का मार्किस

1
लेकिन इसने मेरे लिए मदद की
TheSecond

@EJP मैंने लिनक्स पर एक सर्वर का परीक्षण किया और यह काम किया, लेकिन मैक ओएस पर - नहीं। और बढ़ते बैकलॉग आकार ने मेरी मदद की। मुझे नहीं पता था कि अधिकतम आकार 50 है।
TheSecond

1
आपने कुछ और परखा। सुनो बैकलॉग का इस अपवाद से कोई लेना-देना नहीं है। यह क्लाइंट में रिफ़्यूज़ल्स या टाइमआउट्स को जोड़ने में मदद करता है। अपवाद नहीं 'सॉकेट बंद', जो एक स्थानीय त्रुटि है।
लोर्ने का

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

-1

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

 try {
      /* your code */
 } catch (SocketException e) {
      e.printStackTrace();
      /* insert your failure processings here */
 }

3
यह होगा लोग इन समस्याओं, लेकिन यह नहीं होगा का समाधान उन्हें। करने के लिए हल उन्हें आपको (क) किसी भी संभावित आवेदन प्रोटोकॉल त्रुटियों और (ख) को हल है पास मृत कनेक्शन। केवल अपवादों को ही नहीं, जिनमें से अधिकांश घातक हैं।
लोर्न

@ ईजेपी: बेशक, जब आप एक त्रुटि पकड़ते हैं, तो आपको अपने सॉकेट (संदर्भ) को कैच स्टेटमेंट में साफ करना चाहिए। मैं अनुमान नहीं लगा सकता कि डेवलपर क्या करने जा रहा है। स्वच्छ प्रक्रिया करने के लिए यह अपने दम पर है
elhadi dp ıpן ǝ

यह अनुप्रयोग प्रोटोकॉल समस्या को ठीक करने के लिए डेवलपर पर निर्भर है जो त्रुटि का कारण बनता है, और वहाँ है। कुछ भी नहीं मैं आपका जवाब या कोड है जो उसे मदद करता है। ऐसा करो। 'इसके बीच रीड / राइट ऑपरेशन डालें' इसे ठीक नहीं करता है। आपका उत्तर गलत है।
लोर्ने

@ user207421, डेवलपर पूछता है कि टूटे हुए पाइप को कैसे ठीक किया जाए। मैंने पहले उसे अपने कार्यक्रम को बचाने के लिए (कैच ट्राई) का उपयोग करके संकेत दिया है। इससे प्रोग्राम क्रैश होने से बच जाएगा। तब मैं एक टिप्पणी डालने के लिए उसे साफ प्रसंस्करण करने के लिए संकेत मिलता है। आम तौर पर एक टूटी हुई पाइप त्रुटियों में, कई विकल्प होते हैं, मैं कार्यक्रम के उद्देश्य का अनुमान नहीं लगा सकता हूं, कार्यक्रम बंद करो, कनेक्शन नवीनीकृत करें, डेटा दूषित है या नहीं .... आदि। यह प्रोग्रामर पर निर्भर है कि वह कौन सा विकल्प चुनेगा? मेरे जवाब में क्या गलत था?
elhadi dp ıpɐɥ had '
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.