Theo một câu hỏi gần đây , tôi tự hỏi tại sao trong Java không thể đọc / ghi trên ổ cắm TCP, để phát hiện ra rằng ổ cắm đã được đóng một cách duyên dáng bởi ngang hàng? Điều này dường như luôn xảy ra bất kể người ta sử dụng pre-NIO Socket
hay NIO SocketChannel
.
Khi một máy ngang hàng đóng kết nối TCP một cách duyên dáng, các ngăn xếp TCP ở cả hai phía của kết nối biết về sự thật. Phía máy chủ (phía bắt đầu tắt máy) kết thúc ở trạng thái FIN_WAIT2
, trong khi phía máy khách (phía không phản hồi rõ ràng với việc tắt máy) kết thúc ở trạng thái CLOSE_WAIT
. Tại sao không có phương thức nào trong Socket
hoặc SocketChannel
có thể truy vấn ngăn xếp TCP để xem liệu kết nối TCP bên dưới đã bị chấm dứt hay chưa? Có phải là ngăn xếp TCP không cung cấp thông tin trạng thái như vậy không? Hay đó là một quyết định thiết kế để tránh một cuộc gọi tốn kém vào hạt nhân?
Với sự trợ giúp của những người dùng đã đăng một số câu trả lời cho câu hỏi này, tôi nghĩ rằng tôi biết vấn đề có thể đến từ đâu. Bên không đóng kết nối một cách rõ ràng sẽ ở trạng thái TCP CLOSE_WAIT
có nghĩa là kết nối đang trong quá trình tắt và chờ bên đưa ra CLOSE
hoạt động riêng của mình . Tôi cho rằng nó đủ công bằng để isConnected
trả lại true
và isClosed
trả lại false
, nhưng tại sao không có cái gì đó như thế isClosing
?
Dưới đây là các lớp thử nghiệm sử dụng ổ cắm trước NIO. Nhưng kết quả giống hệt nhau thu được bằng cách sử dụng 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);
}
}
Khi máy khách thử nghiệm kết nối với máy chủ thử nghiệm, đầu ra vẫn không thay đổi ngay cả sau khi máy chủ bắt đầu tắt kết nối:
connected: true, closed: false
connected: true, closed: false
...