हाल ही में एक प्रश्न के अनुवर्ती के रूप में , मुझे आश्चर्य है कि टीसीपी सॉकेट पर पढ़ने / लिखने का प्रयास किए बिना जावा में यह असंभव क्यों है, यह पता लगाने के लिए कि सॉकेट को सहकर्मी द्वारा बंद कर दिया गया है? यह इस बात की परवाह किए बिना होता है कि कोई पूर्व-NIO Socket
या NIO का उपयोग करता है या नहीं SocketChannel
।
जब कोई सहकर्मी किसी टीसीपी कनेक्शन को बंद करता है, तो कनेक्शन के दोनों तरफ स्थित टीसीपी स्टैक तथ्य के बारे में जानता है। सर्वर-साइड (शटडाउन शुरू करने वाला) राज्य में समाप्त होता है FIN_WAIT2
, जबकि क्लाइंट-साइड (वह जो शटडाउन का स्पष्ट रूप से जवाब नहीं देता है) राज्य में समाप्त होता है CLOSE_WAIT
। इसमें कोई विधि क्यों नहीं है Socket
या SocketChannel
यह देखने के लिए TCP स्टैक को क्वेरी कर सकता है कि क्या अंतर्निहित TCP कनेक्शन समाप्त कर दिया गया है? क्या यह है कि टीसीपी स्टैक ऐसी स्थिति जानकारी प्रदान नहीं करता है? या यह कर्नेल में एक महंगी कॉल से बचने के लिए एक डिजाइन निर्णय है?
उन उपयोगकर्ताओं की मदद से जिन्होंने पहले से ही इस प्रश्न के कुछ उत्तर पोस्ट किए हैं, मुझे लगता है कि मैं देख रहा हूं कि समस्या कहां से आ रही है। जो पक्ष कनेक्शन को स्पष्ट रूप से बंद नहीं करता है वह टीसीपी राज्य में समाप्त होता है CLOSE_WAIT
जिसका अर्थ है कि कनेक्शन बंद करने की प्रक्रिया में है और पक्ष द्वारा स्वयं के CLOSE
संचालन को जारी करने की प्रतीक्षा करता है । मुझे लगता है कि यह काफी उचित है कि isConnected
रिटर्न true
और isClosed
रिटर्न false
, लेकिन ऐसा कुछ क्यों नहीं है isClosing
?
नीचे परीक्षण कक्षाएं हैं जो पूर्व-एनआईओ सॉकेट का उपयोग करती हैं। लेकिन NIO का उपयोग करके समान परिणाम प्राप्त किए जाते हैं।
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
...
Socket.close
एक सुंदर करीबी नहीं है।