2014-01-26 6 views

답변

18

클라이언트가 close()을 통해 소켓을 닫고 TCP 닫기 핸드 셰이크가 발생한 일반적인 경우 (channelClosed() 3) 이벤트가 트리거됩니다.

그러나 클라이언트 컴퓨터가 정전이나 LAN 케이블이 연결되지 않아 오프라인 상태가되는 것과 같은 비정상적인 경우에는 연결이 실제로 끊어 질 때까지 많은 시간이 걸릴 수 있습니다. 이 상황을 감지하려면 주기적으로 클라이언트에게 메시지를 보내고 일정 시간 내에 응답을 받아야합니다. 마치 핑과 같습니다. 프로토콜의주기적인 핑 (ping) 및 퐁 (pong) 메시지를 정의해야합니다.이 메시지는 실제로 연결의 상태를 확인하는 것 외에는 아무것도 수행하지 않습니다.

또는 SO_KEEPALIVE을 활성화 할 수 있지만이 옵션의 keepalive 간격은 일반적으로 OS에 따라 다르므로 사용하지 않는 것이 좋습니다.

사용자가 이러한 종류의 동작을 비교적 쉽게 구현할 수 있도록 Netty는 ReadTimeoutHandler을 제공합니다. 일정 시간 동안 인바운드 트래픽이 없을 때 ReadTimeoutHandler이 예외를 발생 시키도록 파이프 라인을 구성하고 exceptionCaught() 처리기 메서드에서 예외가 발생하면 연결을 닫습니다. 정기적 인 핑 메시지를 보내야하는 파티 인 경우 타이머 (또는 IdleStateHandler)를 사용하여 보내십시오.

0

nettop을 사용하는 프로토콜에 따라 다릅니다. ping-like 메시지를 지원하도록 디자인하면 간단히 그 메시지를 보낼 수 있습니다. 그 외에도 Netty는 TCP를 둘러싼 꽤 얇은 래퍼 일뿐입니다.

또한 isOpen() 및 관련을 나타내는 this SO post을 참조하십시오. 그러나 이것은 살아있는 문제를 해결하지 못합니다.

+0

해당 링크의 답변이 대부분 잘못되었습니다. 그래서 더 나은 답변이 있습니다. – EJP

+0

@EJP 링크가 있습니까? 편집을 제안 할 수 있으면 기꺼이 받아 들일 것입니다! –

+0

나의 이해는 tcp가 keep-alive를 내장하고 있다는 것입니다. 이것을 활용할 수 있습니까? –

0

서버를 작성하고 netty가 클라이언트 인 경우 select() 또는 이와 동등한 것을 호출하여 서버가 소켓을 읽을 수있을 때를 감지하고 recv()을 호출하여 연결을 감지 할 수 있습니다. recv()이 0이면 소켓은 클라이언트에 의해 정상적으로 닫혔다. recv()이 -1을 반환하면 실제 오류에 대해 errno 또는 이와 동등한 내용을 확인하십시오. 예외는 거의 없으며 대부분의 오류는 비정상적인 연결 끊김으로 처리해야합니다. 예상치 못한 연결 끊김 문제는 OS가 감지하는 데 오랜 시간이 걸릴 수 있으므로 TCP 연결 유지 기능을 사용하거나 클라이언트가 정기적으로 서버에 데이터를 보내도록해야합니다. 일정 기간 동안 클라이언트로부터 아무 것도 수신되지 않으면 클라이언트가 없어 졌다고 가정하고 연결을 종료하십시오. 클라이언트가 원하면 다시 연결할 수 있습니다.

+0

에서 편집하셨습니다. 질문을 잘못 읽은 것 같습니다. 그는 서버에서 Netty를 사용하는 것 같습니다. – EJP

0

피어에 의해 닫힌 연결에서 읽으면 API에 따라 일종의 스트림 끝 표시가 표시됩니다. 이러한 연결에 쓰면 IOException이 발생합니다 : '연결 재설정'. TCP는 닫힌 연결을 감지하는 다른 방법을 제공하지 않습니다.

TCP keep-alive (a)는 기본적으로 꺼져 있고 (b) 활성화 된 경우 기본적으로 2 시간마다 작동합니다. 이것은 아마도 당신이 원하는 것이 아닙니다. 사용하고 연결이 끊어진 것을 감지 한 후 읽거나 쓰면 위의 재설정 오류가 발생합니다.

+0

Windows 2000 및 이후 버전에서는 'WSAIoctl (SIO_KEEPALIVE_VALS)'를 사용하여 연결 단위로 TCP keep-alive의 원하는 간격을 프로그래밍 방식으로 설정할 수 있습니다. –

관련 문제