2010-08-14 2 views
5

셀렉터를 사용하여 소켓을 실행 중입니다. 소켓이 서버에 연결되어 있는지 확인하려고합니다.Java SocketChannel이 연결 끊김을 감지하지 못합니까?

Boolean connected = _channel.isConnected(); 

항상 true를 반환합니다. 내 컴퓨터에서 공항 (인터넷 연결)을 끄고 소켓이 연결되었는지 여부를 확인하면 여전히 true를 반환합니다. 그 이유는 무엇입니까? 3 초마다 서버에 데이터를 쓰려고 시도하지만 소켓 연결이 끊어진 상태로 변경되지 않습니다.

+0

누군가가 내 질문의 제목을 변경하는 것을 혼란스럽게 생각합니다. 무슨 일 이니? – aryaxt

+0

위 코드를 사용하면 SocketChannel이 여전히 연결되어 있는지 확인할 수 있습니다. 정확히 무엇을 테스트 했습니까? Socket은 제목이나 코드에 표시된 질문이나 채널에서 언급 했습니까? 사람들이 내 대답을 downvoting하기 시작한 이유는 ... (이유를 설명하지 않고 ...) –

+0

1- 메서드를 호출하여 수동으로 소켓을 닫습니다. 그래서 서버에서 연결을 끊은 후에 false가되는 경우입니다. "연결 손실"과 같은 연결 끊김 문제가 있는지 감지하려고하기 때문에 소켓에 ​​서버에 메시지를 보내고 예외가 발생하지 않으면 연결이 끊어지는 것을 감지하지 못합니다. 2- 나는 또한 셀렉터를 사용하고 있다고 언급했다. 그래서 서버에 연결되어 있는지 여부는 isConnected 메서드가 표시되지 않지만 내 소켓이 선택기에 계속 연결되어 있는지 여부가 표시됩니다. 소켓이 셀렉터에 연결되어 있으면 true를 반환합니다. – aryaxt

답변

11

보통이다 OS 레벨 네트워킹을 끄고, 소켓에 쓰기는 예외를 던져야한다. 그래서 연결이 끊어 졌다는 것을 알게됩니다.

하지만 일반적으로 패킷이 전달되는지는 알 수 없습니다. 자바 (아마 너무 C)에서, 패킷 ACK'ed 있는지 확인하는 방법은 없습니다.

TCP ACK를 확인할 수 있다고해도 서버가 또는을 수신했다고 보장하지 않습니다. 대상 머신이 패킷을 수신하여 메모리에 버퍼링했음을 나타냅니다. 그 후 많은 일이 잘못 될 수 있습니다.

정말 확실한 경우 전송 프로토콜에 의존 할 수 없습니다. 응용 프로그램 수준 ACK이 있어야합니다. 즉, 서버 응용 프로그램은 을받은 후 ACK 메시지를 다시 쓰고 클라이언트에서 메시지를 처리했습니다.

클라이언트 관점에서 볼 때 서버에 메시지를 쓰고 서버에서 ACK를 읽으려고합니다. 메시지를 받으면 메시지가 으로 처리되었음을 확신 할 수 있습니다. ACK를 얻지 못하면 무슨 일이 일어 났는지 전혀 모른다. 경험적으로 대부분의 TCP는 실패했습니다. 다음 가능성은 서버가 추락했다는 것입니다. ACK가 클라이언트에 도달 할 수 없다는 것을 제외하고는 모든 것이 OK 일 수도 있습니다.

5

소켓 채널은 connect 메소드를 호출하여 연결할 수 있습니다. 일단 연결되면 소켓 채널은 닫힐 때까지 연결 상태를 유지합니다.

실제 연결이 끊어 지거나 서버에 장애가 발생하여 서버를 더 이상 사용할 수 없으면 채널이 닫히지 않습니다. 연결이 설정되면 isConnected()은 채널을 닫을 때까지 true을 반환합니다.

서버를 계속 사용할 수 있는지 확인하려면 소켓 출력 스트림에 바이트를 보내십시오. 예외가 발생하면 서버를 사용할 수 없습니다 (연결이 끊어짐).


편집 EJP에 대한

- 테스트하고 의견을 재고하고 답변을 몇 가지 코드 : 내 컴퓨터에

public class ChannelTest { 
    public static void main(String[] args) throws UnknownHostException, IOException { 
     Socket google = new Socket(InetAddress.getByName("www.google.com"), 80); 
     SocketChannel channel = SocketChannel.open(google.getRemoteSocketAddress()); 
     System.out.println(channel.isConnected()); 
     channel.close(); 
     System.out.println(channel.isConnected()); 
    } 
} 

출력하면 경우

true 
false 
+2

친애하는 downvoters - 제발 대답이 도움이되지 않는다고 생각한다면 의견을 남기십시오. 적어도 EJP 코멘트는 그의 답변만큼 정확하지 않습니다 ... 질문은 SocketChannels에 관한 것이었고 저는 여전히 확신합니다. 공항을 끄면 isConnected() == false가되지 않습니다. –

+1

나는 안드레아스에 동의한다 : 설명되지 않은 하도는 쓸모 없거나 더 나쁘다. 설명 할 수없는 downvotes를 단순한 site vandalism으로 간주하려고합니다. – EJP

+0

이것이 왜 downvoted인지 이해하지 못한다 – earcam

4

는, isConnected()는 당신을 알려줍니다 여부 당신은 당신이 가지고있는 채널 객체를 연결했고, 분명히는 않지만이, 당신이 그것을 닫은 후에 false를 돌려 지정되지 않은 것 : 안드레아스의 답변을 참조하십시오. 연결이 여전히 존재하는지 여부를 알려주는 것은 아닙니다. 당신은 단지 그것을 사용함으로써 말할 수 있습니다 : -1에서 읽음 또는 예외, 그것은 당신에게 알려줍니다.

+0

'isConnected()'는 원격 서버에 대한 채널을 닫을 때 내 컴퓨터에서'false'를 반환합니다. 실제 답변은 내 대답을 참조하십시오. –

+0

읽기에서'-1'도 작동하지 않습니다. 내가 읽기를 추가하고 차단했습니다 (바이트를 기다리는 중). 그런 다음 네트워크 케이블을 당겨서 응용 프로그램을 계속 차단했습니다 (결과로 '-1'이 표시되지 않음). –

+0

예, 읽기에서 -1은 정상적으로 닫기를 감지합니다. 판독 및 기록이없는 무질서한 클로즈를 검출하는 유일한 방법은 판독 타임 아웃을 이용하는 것이며, 이는 예외를 제공한다. – EJP