SocketChannel Default nonBlocking is false
SocketChannel을 사용할 때 기본적으로 Blocking Mode로 사용된다.
일반적으로 다음과 같이 사용하는 경우 버퍼에 있는 데이터를 읽기 위한 작업 수행 시 Thread Block 발생
이 경우 Read Timeout(soTimeout)을 설정해도 먹히지 않음
Javadoc을 보면 read() 메서드에 대한 timeout은 InputStream을 사용할 때 적용 가능하다고 되어 있음
즉, SocketChannel의 구현체인 SocketChannelImpl의 read() 메서드를 직접 사용하는 경우 InputStream을 사용하지 않고 IOUtil.read()를 호출
InputStream을 사용하여 ReadTimeout 설정
getInputStream()을 통해 실제 ChannelInputStream 반환
이후 SocketInputStream.read(ByteBuffer bb)가 호출됨
이 메서드에서의 특징은
- 소켓 채널의 설정을 Non-Blocking으로 변경
sc.configureBlocking(false);
- 최초 읽기 시도 시 반환된 데이터가 없으면 이후 timeout 설정만큼 소켓을 poll 하여 변화를 감지
int result = sc.poll(Net.POLLIN, to);
- 만약 0보다 작은 값이 반환되었다면 Running Time을 확인하여 타임아웃이라 판단되면 SocketTimeoutException Throw
to -= System.currentTimeMillis() - st; if (to <= 0) throw new SocketTimeoutException();
- 메서드를 Return 하기 전 설정을 원복 하여 Blocking Mode로 바꿈
finally { try { sc.configureBlocking(true); } catch (ClosedChannelException e) { } }
결론
- SocketChannel Blocking Mode에서는 기본적으로 Read Timeout 기능을 제공하지 않음
- InputStream을 사용하는 형태로 Blocking Mode에서도 Read Timeout 기능을 사용할 수 있지만 실제 내부 로직에서는 Non-Blokcing Mode로 임시 변경하여 사용하는 트릭과 같음
참고
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4614802
https://technfun.wordpress.com/2009/01/29/networking-in-java-non-blocking-nio-blocking-nio-and-io/
'자바 개발자되기' 카테고리의 다른 글
Inner Class에 대한 유효성 검사(javax.validation) (0) | 2022.07.02 |
---|---|
Spring JPA findById() 사용 시 주의점 (1) | 2021.07.28 |
@MockBean Spring Context Recreated (0) | 2021.05.24 |
구체적인 Exception Catch를 해야하는 이유 (0) | 2021.04.22 |
Open Session In View와 트랜잭션, 그리고 영속성 컨텍스트 (0) | 2021.03.24 |