2011-11-08 9 views
14

यह एक साधारण टीसीपी सर्वर है। प्रोग्राम समाप्त होने पर मैं सॉकेट को कैसे बंद कर सकता हूं? मैंने कोशिश/अंततः उपयोग किया है और सॉकेट को बंद करने का प्रयास किया है। लेकिन जब मैं प्रोग्राम से बाहर निकलता हूं तो अंत में यह ब्लॉक नहीं चलाता है।मैं सॉकेट को उचित तरीके से कैसे बंद कर सकता हूं?

किसी को भी सही तरीके से सॉकेट को बंद करने के बारे में विचार हो सकता है?

try { 
     socket = new ServerSocket(port); 
     System.out.println("Server is starting on port " + port + " ..."); 
    }catch (IOException e){ 
     System.out.println("Error on socket creation!"); 
    } 

    Socket connectionSocket = null; 
    try{ 
     while(true){    
      try{ 
       connectionSocket = socket.accept(); 
       Thread t = new Thread(new ClientConnection(connectionSocket)); 
       t.start(); 
      }catch (IOException e) { 
       System.out.println("Error on accept socket!"); 
      } 
     } 
    }finally{ 
     this.socket.close(); 
     System.out.println("The server is shut down!"); 
    } 
+1

अपने अंत में ब्लॉक, या अब जावा 7 के साथ आप कोशिश के साथ-संसाधनों ब्लॉक का उपयोग कर सकते हैं, और यह आप के लिए उन्हें बंद हो जाएगा में सॉकेट 'पास()' विधि कॉल। http://www.javacodegeeks.com/2011/07/java-7-try-with-resources-explained.html –

+0

'सर्वर (सॉकेट' कन्स्ट्रक्टर फेंकने के मामले में आपको 'क्लोज़()' को कॉल करने से पहले एक शून्य जांच की भी आवश्यकता है अपवाद। – unholysampler

+0

@ किट हो, एप्लिकेशन कैसे समाप्त हो गया है? – mre

उत्तर

0

आखिरकार कैसे नहीं चल रहा है? शायद, जबकि (सही) की तरह

while (!shutdownRequested) 

कुछ के साथ प्रतिस्थापित किया जाना चाहिए वैकल्पिक रूप से आप एक बंद हुक कि सॉकेट पास

+0

एक नाइट-पिक्य नोट, जावाडोक देखें। आप बंद करना चाहते हैं, नष्ट नहीं करना चाहते हैं। http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html –

+0

इसे प्राप्त नहीं किया, क्या आप और विस्तार कर सकते हैं? –

+0

आप कोशिश कर सकते हैं, संदेश "सर्वर बंद हो जाएगा प्रिंट नहीं होगा!" –

0

ठीक है, तुम कैसे 'प्रस्थान' कार्यक्रम कर संभालती बना सकते हैं? finally निष्पादित किया जाएगा यदि कोई अपवाद फेंक दिया जाएगा या यदि कोशिश ब्लॉक "निष्पादन" में अपना निष्पादन समाप्त कर देता है लेकिन मुझे लगता है कि आपके while(true) की वजह से यह "कठिन" हो सकता है।

सॉकेट को बंद करने के लिए आपको socket.close() का उपयोग करना चाहिए और मैं आपको सलाह दूंगा कि आप नष्ट समारोह पर भरोसा न करें।

10

अपने ServerSocket बनाने के बाद, आप जोड़ सकते एक JVM समाप्ति पर इसे बंद करना, कुछ इस तरह:

Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){ 
    try { 
     socket.close(); 
     System.out.println("The server is shut down!"); 
    } catch (IOException e) { /* failed */ } 
}}); 

लागू ServerSocket#close अवरुद्ध ServerSocket.accept कॉल समाप्त कर देगा, यह एक SocketException फेंकने के लिए कारण। हालांकि, ध्यान दें कि जबकि लूप में IOException की आपकी वर्तमान हैंडलिंग का मतलब है कि आप बंद सॉकेट पर स्वीकार करने के प्रयास के दौरान लूप को फिर से दर्ज करेंगे। JVM अभी भी समाप्त हो जाएगा, लेकिन यह थोड़ा अस्पष्ट है।

यदि आप एक्लिप्स (कम से कम विंडोज़ पर) में कंसोल एप्लिकेशन को समाप्त करते हैं तो शटडाउन हुक नहीं चलते हैं। लेकिन यदि आप सामान्य कंसोल में CTRL-C जावा करते हैं तो वे चलते हैं। उनके लिए चलाने के लिए, आपको सामान्य रूप से समाप्त होने के लिए JVM की आवश्यकता होती है, उदा। SIGINT के बजाय SIGINT या SIGTERM (हत्या -9)।

ग्रहण या कंसोल में निष्पादित करने वाला एक सरल प्रोग्राम यह प्रदर्शित करेगा।

public class Test implements Runnable { 

    public static void main(String[] args) throws InterruptedException { 
    final Test test = new Test(); 
    Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){ 
     test.shutdown(); 
    }}); 
    Thread t = new Thread(test); 
    t.start(); 
    } 

    public void run() { 
    synchronized(this) { 
     try { 
     System.err.println("running"); 
     wait(); 
     } catch (InterruptedException e) {} 
    } 
    } 

    public void shutdown() { 
    System.err.println("shutdown"); 
    } 
} 
+1

क्या 'ShutDownHook हमेशा निष्पादित हैं? क्या उन पर भरोसा करना एक आम और सुरक्षित अभ्यास है? – Gevorg

+1

@ गेवोर्ग जावाडोक कहता है, शटडाउनहुक सामान्य रूप से समाप्त होने पर बाहर निकलने से पहले JVM द्वारा चलाए जाते हैं। यदि आप जावा प्रक्रिया को "मार -9" करते हैं, तो वे नहीं करेंगे। मैंने वाणिज्यिक एंटरप्राइज़ सॉफ़्टवेयर में सर्वर प्रक्रियाओं के व्यवस्थित शट डाउन के लिए विश्वसनीय रूप से उपयोग किए गए शट डाउन हुक को देखा है। – sudocode

+0

उनकी समस्या 'स्वीकार {)' लूप से 'अंत में {}' ब्लॉक में हो रही है, न कि वहां पहुंचने के बाद क्या करना है। – EJP

7

आपके विशेष मामले में कोई ज़रूरत नहीं है, प्रोग्राम चालू होने पर ऑपरेटिंग सिस्टम आपके लिए सभी टीसीपी सॉकेट बंद कर देगा।

+4

काम नहीं करेगा आप सही कह रहे हैं कि जब प्रोग्राम बाहर निकलता है तो ओएस सभी टीसीपी सॉकेट बंद कर देगा, लेकिन मैं नहीं चाहता सभी मामलों में * नहीं "ज़रूरत नहीं है"। यह इस बात पर निर्भर करता है कि आपको इस कार्यक्रम से बाहर निकलने से पहले सुनाई गई बंदरगाह को रिलीज़ करने की आवश्यकता है (हालांकि इस मामले में, यह ठीक होना चाहिए क्योंकि ओपी प्रोग्राम से निकलने पर इसे बंद करना चाहता है) – xav

2
javadoc से

:

जावा रनटाइम स्वचालित रूप से इनपुट और आउटपुट धाराओं, ग्राहक सॉकेट, और सर्वर सॉकेट बंद कर देता है, क्योंकि वे कोशिश के साथ-संसाधनों बयान में बनाया गया है।

इसके अलावा

finalize() विधि जावा आभासी मशीन (JVM) से बुलाया से पहले कार्यक्रम कार्यक्रम और रिहाई संसाधनों को साफ करने के लिए एक मौका देने के लिए बाहर निकलता है। मल्टी-थ्रेडेड प्रोग्राम्स को सभी फाइलें बंद करनी चाहिए और सॉकेट्स जो वे बाहर निकलने से पहले उपयोग करते हैं, इसलिए उन्हें संसाधन भुखमरी का सामना नहीं करना चाहिए।server.close() पर finalize() विधि पर कॉल इस प्रोग्राम में प्रत्येक थ्रेड द्वारा उपयोग किए गए सॉकेट कनेक्शन को बंद कर देता है।

protected void finalize(){ 
//Objects created in run method are finalized when 
//program terminates and thread exits 
    try{ 
     server.close(); 
    } catch (IOException e) { 
     System.out.println("Could not close socket"); 
     System.exit(-1); 
    } 
    } 
संबंधित मुद्दे