दिलचस्प पोस्ट
javac त्रुटि: एनोटेशन प्रसंस्करण स्पष्ट रूप से अनुरोध किया जाता है, तो कक्षा नाम केवल स्वीकार किए जाते हैं JavaScript में JSON.stringify () के विकल्प Xcode 8 बीटा 4 स्विफ्ट 3 – "गोल" व्यवहार बदल गया है 64 बिट आवेदन में 32 बिट डीएलएल लाइब्रेरी को लोड करें एचटीएमएल टैग निकालें लेकिन अंदरूनी HTML रखें वसा जार क्या है? conda, condi, conde, condu एक iPhone ऐप में निर्यात – अनुपालन निर्यात करें माता-पिता को परिभाषित किए बिना रनटाइम पर TRICHEdit का उपयोग करना रोचक 'बिल्कुल 1 तर्क (2 दिया)' पायथन त्रुटि लेता है डीजेंगो एक्सल एक्सएलवीटी एक इंडेक्स द्वारा वेक्टर को विभाजित करने और उस विभाजन पर ऑपरेशन करने के लिए रेशमी आर कोड NHibernate और SqlServer में डेटा अंकेक्षण क्या यह संभवतः आउटपुट संख्याओं को प्रारूपित करने के लिए matlab में संभव है? रिक्त अभिव्यक्तियां सी / सी ++ में कानूनी क्यों हैं?

यह क्यों असंभव है कि आईओ के प्रयास किए बिना, यह पता लगाने के लिए कि टीसीपी सॉकेट को सहकर्मी ने शानदार ढंग से बंद कर दिया था?

एक हालिया प्रश्न का अनुपालन करते समय, मुझे आश्चर्य है कि जावा में एक टीसीपी सॉकेट पढ़ने / लिखने के प्रयास के बिना, यह समझने में क्यों असंभव है कि यह पता लगाया जा सकता है कि गर्तिका को सहयोगी ने बंद कर दिया है? ऐसा प्रतीत होता है कि क्या कोई पूर्व-निओ Socket या एनआईओ Socket SocketChannel का उपयोग करता है

जब किसी सहकर्मी ने टीसीपी कनेक्शन बंद कर दिया, तो कनेक्शन के दोनों किनारों पर टीसीपी स्टैक तथ्य के बारे में जानता है। सर्वर-साइड (जो शट डाउन आरंभ करता है) को राज्य FIN_WAIT2 में समाप्त होता है, जबकि क्लाइंट-साइड (जो कि शट डाउन का स्पष्ट रूप से प्रतिसाद नहीं देता है) राज्य में समाप्त होता है CLOSE_WAITSocket या Socket SocketChannel में क्यों कोई तरीका नहीं है, जो कि टीसीपी स्टैक की जांच कर सकता है यह देखने के लिए कि क्या अंतर्निहित टीसीपी कनेक्शन समाप्त हो गया है? क्या ऐसा है कि टीसीपी स्टैक ऐसी स्थिति जानकारी प्रदान नहीं करता है? या क्या यह कर्नेल में महंगी कॉल से बचने का एक डिजाइन निर्णय है?

ऐसे उपयोगकर्ताओं की सहायता से, जिन्होंने पहले से ही इस प्रश्न के कुछ उत्तर पोस्ट किए हैं, मुझे लगता है कि मुझे यह पता है कि यह समस्या कहां से आ रही है। जिस पक्ष ने कनेक्शन को स्पष्ट रूप से बंद नहीं किया है वह टीसीपी स्थिति में समाप्त होता है CLOSE_WAIT जिसका अर्थ है कि कनेक्शन बंद होने की प्रक्रिया में है और पक्ष के लिए अपने स्वयं के CLOSE कार्रवाई जारी करने की प्रतीक्षा करता है। मुझे लगता है कि यह काफी उचित है कि isConnected रिटर्न true और isClosed रिटर्न false , लेकिन ऐसा क्यों नहीं है?

नीचे टेस्ट क्लास हैं जो प्री-एनआईओ सॉकेट्स का उपयोग करते हैं। लेकिन समान परिणाम एनआईओ के माध्यम से प्राप्त किए जाते हैं।

 import java.net.ServerSocket; import java.net.Socket; public class MyServer { public static void main(String[] args) throws Exception { final ServerSocket ss = new ServerSocket(12345); final Socket cs = ss.accept(); System.out.println("Accepted connection"); Thread.sleep(5000); cs.close(); System.out.println("Closed connection"); ss.close(); Thread.sleep(100000); } } import java.net.Socket; public class MyClient { public static void main(String[] args) throws Exception { final Socket s = new Socket("localhost", 12345); for (int i = 0; i < 10; i++) { System.out.println("connected: " + s.isConnected() + ", closed: " + s.isClosed()); Thread.sleep(1000); } Thread.sleep(100000); } } 

जब टेस्ट क्लाइंट टेस्ट सर्वर से कनेक्ट होता है तो सर्वर कनेक्शन के बंद होने के बाद भी आउटपुट रहता है:

 connected: true, closed: false connected: true, closed: false ... 

Solutions Collecting From Web of "यह क्यों असंभव है कि आईओ के प्रयास किए बिना, यह पता लगाने के लिए कि टीसीपी सॉकेट को सहकर्मी ने शानदार ढंग से बंद कर दिया था?"

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

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

यदि आपको दूसरी तरफ अपनी सॉकेट बंद करने की प्रतीक्षा करनी है, तो आपको अपने एफआईएन के लिए इंतजार करना होगा। और इसे हासिल करने के लिए, आपको Socket.getInputStream().read() < 0 का पता Socket.getInputStream().read() < 0 , जिसका मतलब है कि आपको अपनी सॉकेट बंद नहीं करना चाहिए, क्योंकि यह अपने InputStream को बंद कर देगी।

सी में मैंने जो किया, और अब जावा में, इस तरह के एक सिंक्रनाइज़ किए गए बंद को प्राप्त करने से ऐसा किया जाना चाहिए:

  1. शटडाउन सॉकेट आउटपुट (दूसरे छोर पर एफआईएन भेजता है, यह आखिरी चीज है जो कभी इस सॉकेट द्वारा भेजी जाएगी)। इनपुट अभी भी खुला है ताकि आप read() को read() सकें और रिमोट close() पता लगा सकें close()
  2. गर्तिका InputStream पढ़ें जब तक हम दूसरे छोर से उत्तर-एफआईएन प्राप्त नहीं करते (जब तक यह एफआईएन का पता लगाता है, यह एक ही सुंदर डॉकनेक्शन प्रक्रिया से गुज़रता है)। यह कुछ ओएस पर महत्वपूर्ण है क्योंकि वे सॉकेट को वास्तव में बंद नहीं करते जब तक कि इसके बफ़र में से एक अभी भी डेटा शामिल करता है। उन्हें "भूत" सॉकेट कहा जाता है और ओएस में विवरणकर्ता संख्या का उपयोग (जो अब आधुनिक ओएस के साथ एक मुद्दा नहीं हो सकता है)
  3. गर्तिका को बंद करें (या तो Socket.close() कॉल करके या इसके InputStream या OutputStream बंद कर)

जैसा कि निम्नलिखित जावा स्निपेट में दिखाया गया है:

 public void synchronizedClose(Socket sok) { InputStream is = sok.getInputStream(); sok.shutdownOutput(); // Sends the 'FIN' on the network while (is.read() > 0) ; // "read()" returns '-1' when the 'FIN' is reached sok.close(); // or is.close(); Now we can close the Socket } 

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

@ वारेनडेव ने अपनी टिप्पणी में बताया, प्रोग्राम में डेटा (आवेदन परत) को छोड़ने से आवेदन परत पर एक गैर-अनुरुप वियोग का कारण बनता है: हालांकि सभी डेटा टीसीपी परत ( while लूप) पर प्राप्त हुए थे, उन्हें त्याग दिया जाता है।

1 : " जावा में मौलिक नेटवर्किंग " से: अंजीर देखें। 3.3 पी .45, और पूरे §3.7, पीपी 43-48

मुझे लगता है कि यह सॉकेट प्रोग्रामिंग प्रश्न का अधिक है। जावा सिर्फ गर्तिका प्रोग्रामिंग परंपरा का पालन कर रहा है

विकिपीडिया से :

टीसीपी एक कंप्यूटर पर एक प्रोग्राम से दूसरे प्रोग्राम पर बाइट्स की एक धारा के विश्वसनीय, आदेशबद्ध वितरण प्रदान करता है।

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

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

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

अंतर्निहित सॉकेट्स एपीआई में ऐसी सूचना नहीं है

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

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

जब एक टीसीपी कनेक्शन स्थापित होता है और एक पीयर ने अपने सॉकेट पर shutdownOutput() close() या shutdownOutput() कॉल करता है, तो कनेक्शन के दूसरे पक्ष पर गर्तिका CLOSE_WAIT स्थिति में बदलाव करती है। सिद्धांत रूप में, टीसीपी स्टैक से पता लगाना संभव है कि सॉकेट getsockopt() read/recv getsockopt() स्थिति में read/recv बिना getsockopt() किए बिना (उदाहरण के लिए, getsockopt() लिनक्स पर: http://www.developerweb.net/forum/showthread.php?t = 43 9 5 ), लेकिन यह पोर्टेबल नहीं है

जावा की Socket क्लास को बीएसडी टीसीपी सॉकेट के बराबर अमूर्तता प्रदान करने के लिए डिज़ाइन किया गया है, संभवतः क्योंकि यह एब्स्ट्रक्शन का स्तर है जिसके लिए लोग टीसीपी / आईपी एप्लीकेशन प्रोग्रामिंग करते हैं बीएसडी कुर्सियां ​​सिर्फ आईईईटी (जैसे, टीसीपी) के अलावा अन्य सॉकेट्स का समर्थन करने वाले सामान्यीकरण हैं, इसलिए वे एक सॉकेट के टीसीपी राज्य को खोजने का एक पोर्टेबल तरीका प्रदान नहीं करते हैं।

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

यह पता लगा रहा है कि क्या (टीसीपी) सॉकेट कनेक्शन के दूरस्थ पक्ष को बंद कर दिया गया है, जावा.संकेत.एंडयूआरजीन्टडेटा (इंट) पद्धति के साथ किया जा सकता है, और IOException को पकड़ने पर यह फेंकता है कि रिमोट साइड कम हो। यह जावा-जावा और जावा-सी के बीच परीक्षण किया गया है

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

यदि आप वास्तव में अपने प्रोटोकॉल में ओओबी डेटा का उपयोग करते हैं, तो आपका माइलेज अलग-अलग हो सकता है

यह एक दिलचस्प विषय है मैंने जावा कोड को अभी जांचने के लिए खोला है मेरी खोज से, दो अलग-अलग समस्याएं हैं: पहला टीसीपी आरएफसी ही है, जो दूरस्थ रूप से बंद सॉकेट के लिए आधे-द्वैध में डेटा संचारित करने की अनुमति देता है, इसलिए दूरस्थ रूप से बंद सॉकेट अभी भी आधे खुले हैं। आरएफसी के अनुसार, आरएसटी कनेक्शन को बंद नहीं करता है, आपको स्पष्ट ABORT आदेश भेजने की आवश्यकता है; तो जावा आधे बंद सॉकेट के माध्यम से डेटा भेजने के लिए अनुमति देता है

(दोनों समापन बिंदु पर करीबी स्थिति को पढ़ने के लिए दो तरीके हैं।)

दूसरी समस्या यह है कि कार्यान्वयन कहता है कि यह व्यवहार वैकल्पिक है। जैसा कि जावा पोर्टेबल होने का प्रयास करता है, उन्होंने सबसे अच्छा सामान्य सुविधा को लागू किया। (ओएस, आधा द्वैध के कार्यान्वयन) का एक मानचित्र बनाए रखना एक समस्या होगी, मुझे लगता है

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

… एक और कारण है कि मैं वास्तव में एनआईओ जावा कक्षाओं से नफरत करना शुरू कर रहा हूं। ऐसा लगता है कि सब कुछ थोड़ा सा गधा है

यह जावा की (और अन्य सभी 'के बारे में जो मैंने देखा है) दोष है ओ ओ सॉकेट कक्षाएं – चयन प्रणाली कॉल में कोई पहुंच नहीं है

सी में सही उत्तर:

 struct timeval tp; fd_set in; fd_set out; fd_set err; FD_ZERO (in); FD_ZERO (out); FD_ZERO (err); FD_SET(socket_handle, err); tp.tv_sec = 0; /* or however long you want to wait */ tp.tv_usec = 0; select(socket_handle + 1, in, out, err, &tp); if (FD_ISSET(socket_handle, err) { /* handle closed socket */ } 

यहाँ एक लंगड़ा समाधान है एसएसएल का उपयोग करें;) और एसएसएल टीडाउन पर एक करीबी हाथ मिलाना है ताकि आप को बंद कर दिया जा सकने वाले सॉकेट के बारे में सूचित किया गया हो (ज्यादातर लागू करने के लिए ऐसा प्रतीत होता है जो कि एक प्रसाधन हैंडशेक टीडाउन करना है)।

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

अधिक जानकारी के लिए यूनिक्स सॉकेट अकसर किये गए सवाल देखें

केवल लिखता है कि पैकेटों का आदान-प्रदान किया जाना चाहिए जो कि कनेक्शन के नुकसान के लिए निर्धारित किया जा सकता है। एक आम काम के आसपास केईईईईईईईप विकल्प का उपयोग करना है

जब आधे-खुले जावा सॉकेट्स से निपटने की बात आती है, तो एक को इन्पुट शटडाउन () और isOutputShutdown () पर नजर रखना चाहिए ।