네트워크 프로그램 문제 (CLOSE_WAIT) 해결 부탁
글쓴이: 안상준 / 작성시간: 토, 2003/08/16 - 2:24오후
네트워크 프로그램을 짜다가 CLOSE_WAIT가 생겨서 서버쪽의 host가 hang됩니다. CLOSE_WAIT를 해결할 수 있는 방법이 있나요?
발생하는 현상는
클라이언트와 서버가 통신을 하는 상태에서 갑자기 클라이언트의 Process를 강제로 종료를 시켰습니다. 그랬더니 서버쪽에서 CLOSE_WAIT가 생깁니다. 이렇게 여러번 클라이언트를 종료했더니 서버쪽에 CLOSE_WAIT로 인해 Hang됩니다.
서버쪽의 socket엔 KEEP_ALIVE를 설정했고, 클라이언트쪽에는 SO_LINGER 옵션을 주었습니다.
글을 찾아보니 CLOSE_WAIT는 주로 클라이언트가 갑자기 crash될때 생기는 거라고 하는데, CLOSE_WAIT를 없앨 수 있는 방법은 없나요.. 서버 프로세스를 restart하지 않고, 프로그래밍으로 해결할 수 있는 방법을 알려주시면 감사하겠습니다.
Forums:
CLOSE_WAIT 인경우는 소켓이 상대방이 종료되었으므로,이쪽에서도
CLOSE_WAIT 인경우는 소켓이 상대방이 종료되었으므로,
이쪽에서도 종료해야한다는 의미입니다.
서버쪽이므로, 상대의 socket이 reset 되었다면,
(주로 recv 에서 -1 을 돌리는 것이겠지요.) 그 디스크립터를
close 해주면 되는 것입니다.
hang이 걸린다는 것은 다른 오류가 있기 때문인것 같은데요..?
---
http://coolengineer.com
CLOSE_WAIT는 netstat -atn으로 보았을때 약 170개
CLOSE_WAIT는 netstat -atn으로 보았을때 약 170개 정도가 있었습니다. 이 CLOSE_WAIT는 약 6시간정도 계속 보였습니다. 그 이후로는 그냥 서버 restart하였습니다. 서버쪽에서 CLOSE_WAIT가 생기면 Client쪽 (active close을 수행한 쪽)은 FIN_WAIT2 상태가 되는데, FIN_WAIT2는 fin_timeout으로 특정 시간이 되면 없어집니다. 그렇지만 서버쪽은 클라이언트의 crash인 경우는 무한하게 CLOSE_WAIT 상태가 되고, 이러한 state가 많으면 많을 수록 어느 한계치에 되면 서버쪽에서 tcp connect를 못받게 되고 hang이 됩니다.
이러한 경우엔 서버쪽에서 CLOSE_WAIT가 안 생기기게 하는 방법을 알고 싶습니다. 도움 부탁드립니다.
client 쪽 응답을 기다리는 쪽, 아마 select 나 recv 가
client 쪽 응답을 기다리는 쪽, 아마 select 나 recv 가 될텐데, 그 쪽에서 에러처리를 잘하고 있는데도,
CLOSE_WAIT 상태로 계속 있는건가요?
---
http://coolengineer.com
[quote="안상준"]CLOSE_WAIT는 netstat -atn으로
일반적으로 close() 함수를 사용할 경우 TCP 종료 패킷이 모두 송수신 된 다음에 프로그램이 종료되지 않습니다.!!
이를 위해 shutdown 함수 및 recv() 함수를 사용하여 네개의 패킷이 모두
송수신 되는 것을 확인하는 것이 좋습니다.
위에서 CLOSE_WAIT 상태라는 것은 recv FIN / send ACK 상태인데
서버측에서 이를 제대로 처리해 주지 못하는 것입니다.
1. trace를 통하여 프로세스가 블럭킹 상태로 빠지는지 확인.
2. tcpdump를 통해 종료 패킷이 모두 보이는지 확인.
3. 클라이언트에서 종료를 close()를 사용하지 말고 shutdown 사용
4. kill 시그널 시 TCP 종료 부분 추가
특히 클라이언트 종료시 발생하는 문제라고 했는데
이경우 TCP 종료 패킷을 모두 송수신 한 후 프로세스가 종료되야 하는데
그렇지 못해서 발생하는 문제인것 같습니다.
Effective TCP/IP Programming, Jon C. Snader, Wesley
위의 책을 보시면 TCP 종료에 관련된 내용이 있습니다.
괜찮은 책이니 한번 사서 보심이 좋을것 같습니다. :-)
不狂不及
서버쪽 코드에서
위에 분들 말씀대로, 서버쪽 코드에서 예외처리를 해주면 해결 됩니다.
SIGPIPE 받아서 close 해줄수 있는 코드면 그렇게 해주어도 될듯하고,
아니면 socket api의 리턴값을 체크해서 close를 해주는 코드가 들어 가 있는지
확인해보세요.
댓글 달기