2009-10-02 12 views
6

मेरे पास इस कोड के साथ एक सर्वर थ्रेड है:ServerSocket.accept() पर अवरुद्ध थ्रेड को अनब्लॉक कैसे करें?

public void run() { 
    try { 
     ServerSocket server; 
     EneaLog.printLog("Server is running."); 
     server = new ServerSocket(this.portnumber); 

     while (true) { 
      new EneaServerConnection(server.accept(), this.project,stopped).start(); 
      if (stopped) { 
       EneaLog.printLog("Server safe-shutdown completed."); 
       EneaLog.printLog("Hi!"); 
       server.close(); 
       return; 
      } 
     } 
    } catch (IOException ex) { 
     Logger.getLogger(EneaServer.class.getName()).log(Level.SEVERE, null, ex); 
     project.getExceptionHandler().handler(ex); 
    } 
} 

और इस तरह की एक शट डाउन विधि:

public void shutdown() { 
    EneaLog.printLog("Server shutdown NOW!"); 
    stopped = true; 
} 

मैं चाहता हूं कि शट डाउन सर्वर पर प्रतीक्षा कर रहे थ्रेड को अनवरोधित कर सके। अस्वीकरण() अन्यथा मुझे अवश्य ही सर्वर शट डाउन से पहले कनेक्शन की प्रतीक्षा करें।

मैं shutdown() में server.close() नहीं कर सकता क्योंकि मुझे पंजीकृत क्लाइंट को सिग्नल करना होगा कि सर्वर नीचे आ रहा है।

कोई विचार?

उत्तर

4

मैं अपना कोड डिज़ाइन करने का प्रयास करता हूं ताकि इसे किसी बाधा के साथ "बंद" किया जा सके। मुख्य रूप से, ऐसा इसलिए है क्योंकि चल रहे कार्यों को रद्द करने के लिए जावा के समवर्ती पैकेज में Executor ढांचा interrupt का उपयोग करता है। साथ ही, "शटडाउन" कार्य को मारे जाने वाले कार्य के किसी भी आंतरिक को जानने की आवश्यकता नहीं है।

हालांकि, accept के लिए एक कॉल व्यवधान का जवाब देंगे नहीं जब तक यह created from a ServerSocketChannel. है एक सर्वर एक ServerSocket निर्माता के साथ बनाया बीच में आता है पर ध्यान नहीं देगा, और मैं इस पुन: कॉन्फ़िगर करने के लिए एक रास्ता नहीं मिला है।

यदि आप सर्वर बनाता है जो कोड नहीं बदल सकते हैं, तो सर्वर सॉकेट पर close पर कॉल करने के लिए एक और थ्रेड की व्यवस्था करें। यह सर्वर सॉकेट बनाने के लिए उपयोग की जाने वाली विधि के बावजूद, accept पर अवरुद्ध थ्रेड में अपवाद भी उठाएगा।

एसएसएल का उपयोग करते समय यह वास्तव में एक बड़ा दर्द साबित होता है। एक JSSE सॉकेट InterruptibleChannel से नहीं बनाया गया है, और थ्रेड पर एक साधारण बाधा का जवाब नहीं देगा।


मैंने अभी देखा है कि सवाल यह कहता है कि सर्वर को सूचित किए बिना सर्वर को बंद नहीं किया जा सकता है। अपने बंद होने में सॉकेट परिणामों को सफलतापूर्वक बाधित करना।

accept पर कॉल पर यह कोई समस्या नहीं होनी चाहिए, क्योंकि सर्वर सॉकेट को स्वीकार करने में अवरुद्ध होने पर क्लाइंट कनेक्ट नहीं है। यह केवल Socket उदाहरणों के लिए एक मुद्दा होना चाहिए, जो मौजूदा कनेक्शन का प्रतिनिधित्व करता है।

यदि यह अधिसूचना आवश्यकताओं को पूरा नहीं करता है, तो गैर-अवरोधन मोड में एनआईओ के ServerSocketChannel का उपयोग करने के लिए एक पुनर्विक्रय आवश्यक हो सकता है।

+0

मिमी अच्छा जवाब .. शायद मैं समस्या के दृष्टिकोण को बदल सकता हूं। मैं कोशिश-पकड़ के साथ क्लाइंट-साइड में सर्वर शटडाउन का प्रबंधन करता हूं। –

0

क्या आपने Thread.interrupt() को आजमाया है?

इस सूत्र एक व्यवधान कारक चैनल पर एक आई/ओ ऑपरेशन में अवरुद्ध है तो चैनल बंद हो जाएगा, थ्रेड बाधा स्थिति का गठन किया जाएगा, और धागा एक ClosedByInterruptException प्राप्त होगा।

इस सूत्र एक चयनकर्ता तो धागा की बाधा स्थिति की स्थापना की जाएगी में अवरुद्ध है और यह चयन आपरेशन से तुरंत वापस आ जाएगी, संभवतः एक गैर शून्य मूल्य के साथ, तो बस के रूप में अगर चयनकर्ता के Wakeup विधि का आह्वान किया गया था।

+0

मैंने इस.interrupt() के साथ प्रयास किया है; शटडाउन() में काम नहीं करता है ... –

+0

आपको इसे उस थ्रेड पर कॉल करने की आवश्यकता है जिसे आप बाधित करना चाहते हैं (यानी अवरुद्ध एक) –

2

आपको सॉकेट को किसी अन्य थ्रेड से बंद करने में सक्षम होना चाहिए।

2

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

+0

आखिरकार आप इस समस्या को कैसे हल करते हैं? कई लोग कहते हैं कि करीबी काम करेगा, लेकिन यह मेरे मामले में काम नहीं करता जो लिनक्स पर चलता है। – Djvu

1

मुझे एक ही समस्या का सामना करना पड़ा है। मेरे काम करने वाले समाधान में सर्वर सॉकेट ऑब्जेक्ट (serverSocket.close()) को बंद करने में शामिल है; ऐसा करने से स्वीकृति() विधि को सॉकेटएक्सप्शन फेंकने का कारण बन जाएगा, जो आप करना चाहते हैं।

विन्सेंट

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