요즘 하는 알바중에 nio 쓰는 일이 있습니다. 금년 여름에도 nio기반의 p2p 파일공유 프레임워크쪽 알바를 했었기에 이번에도 거침없이 뛰어들었습니다. 그렇게 뛰어들은지 어느덧 2주가 되어갑니다.
Selector에 등록한 SelectableChannel을 상속받은 SocketChannel을 분명히 close 했는데 어이없게 안끊기는 겁니다. 혹시나 하며 패킷을 캡춰해봤지만 FIN도 안보내고 RST조차 안보냅니다. 우어어 T-T
안끊겼다는 것을 판단한 기준은 Destination host에서 자신이 끊긴줄 모른다는 것이고, TCP Layer에선 FIN/RST가 가지 않았다는 것입니다. socket.close()를 하고 isClosed를 출력해봐도 true고...
코드를 살펴보다보니, 위같은 상황은 select loop thread가 아닌 곳에서 해당 채널을 닫았을때만 일어나는 상황이였습니다. 그렇다면 Selector.select()가 block 되어있을때 SocketChannel.close를 불러봐야 blocking이 안풀린다는 건가 봅니다. 아니 그래도!! 최소한 SocketChannel을 닫았으면 FIN은 가야하는거 아닙니까 --?
여차여차해서 java.net.Socket의 shutdownInput, shutdownOutput을 쓰게 되었습니다. shutdownInput은 단지 InputStream이나 read쪽에 EOF를 대체해줍니다. 최소한 Selector가 OP_READ를 던지게 해줄수 있는데, shutdownInput만 하고 close했는데 여전히 반응 없습니다. shutdownOutput을 함께 해주고 close하니까.. 앗싸! 바로 닫히긴 하는데, OP_READ에서 EOF가 좀 오랫동안 (0.1초정도) 지속된 후에 닫힙니다. 결국 shutdownIn/Output을 한 후에 close하면 바로 상대쪽에서 끊깁니다. 그러나.. 뒤가 찝찝해서 이것저것 문서를 더 뒤져봅니다.
java.nio.channels.Selector의 class-doc을 보니, select 메서드에서 blocking 되어있을때 이를 빠져나오게 하는데 3가지 케이스가 있다합니다.
By invoking the selector's wakeup method. By invoking the selector's close method, or By invoking the blocked thread's interrupt method, in which case its interrupt status will be set and the selector's wakeup method will be invoked
2, 3번째 방법은 select loop를 종료시켜버립니다. 결국 wakeup을 사용해보기로 결정!
아아 잘됩니다. 정상적으로 OP_READ를 받아서 close처리가 되고 FIN도 잘 보냅니다. 클라이언트도 정상적으로 종료됩니다. 그런데 채널의 close 메서드에서 허구헌날 Selector.wakeup을 부르는건 말도 안되므로 current thread가 Select하는 thread가 아닐 경우에만 wakeup을 하도록 했습니다. 얏호오
그렇게 어느덧 또 AM 03:35가 되버린것 입니다.
Continue Reading
Discover more thoughts and insights
11월 12일
어제는 11월 11일. 빼빼로데이 였습니다. 사람을 만날 정신이 없던 하루였기 때문에 물리적인 빼빼로를 전달하는 일은 없었고 SMS 상용구를 통한 빼빼로 전달만이 있었습니다. 사회가 만들어놓은, 실제로 SMS를
훌륭한 리더
비자아 프로그래밍은 자아를 업무로부터 격리시킬 것을 추천한다. 사람들은 각기 다른 자아를 갖고 있기 때문에, 배가 산으로 가는 경우가 많아지기 때문이다. egoless가 아닌 ego-driven을 할 경우,
Android 스터디: 계산기 만들기
저번 포스트에 이어 오늘은 Android로 계산기를 만들어보도록 하겠습니다. Eclipse 에 ADT 설치까지 마치셨나요? 그럼 헬로월드 실행도 성공하셨을테니, 바로 계산기를 만들어보도록 하겠습니다. 먼저 UI