본문 바로가기

Programing/Network

소켓 종료와 TIME_WAIT(Socket termination and TIME_WAIT)


출처 : http://kukuta.tistory.com/27

 오늘은 소켓의 종료와 그에 따라 발생하는 소켓의 상태 변화에 대해 알아 보도록 하겠다.

 먼저 소켓은 생성될 때는 3-way hand shaking을 통해서 생성되지만, 종료 될때는 한단계 더 많은 4-way hand shaking을 거쳐 종료 된다.

four way handshake

four way handshake


  위에서 분명히 4-way.. 4단계라고 이야기 했다. 그럼 어떤 4단계를 거치는지 알아 보자.

  1. A가 B에게 연결 종료를 요청한다.
  2. B는 바로 종료를 하는 것이 아니라, 단순히 ACK만을 날리고 있다. B도 종료 하기 전에 할
     일이 있기 때문에 바로 FIN을 날리지 않고, 단순히 ACK를 날리고 CLOSE_WAIT 상태로 넘어
     간다.
 3. 볼일을 다 보고난 B는 이제서야 FIN을 날리고 연결을 종료 하고자 한다.
 4. A는 B의 FIN을 잘 받았다는ACK를 B에게 보내게 되고, A의 ACK를 받으면 B는 종료한다.

 4의 과정에서 A는 ACK를 날리고 난후 소켓이 제거될때 까지 TIME_WAIT상태에 있게 되며 이 시간은 대략 30 초 정도지만 시스템 마다 다르다.
 TIME_WAIT에 있는 동안에는 커널이 주소와 port를 바인딩 하고 있기때문에 재사용 할 수가 없다. 게다가 TIME_WAIT에 있는 주소와 port를 재사용 요청을 하면 TIME_WAIT 시간을 더욱 늘릴 뿐이다.
 
 그렇다면 이렇게 불편한 TIME_WAIT를 왜 사용해야만 하는가??
 만일 A가 B로 보낸 마지막 종료 메시지(SEQ:5001,ACK:6002) 이후 바로 종료 했다고 가정하자. 그런데 라우터의 문제라던지 기타등등의 네트워크 상에서 발생하는 어떠한 원인에 의해 마지막 종료 메시지가 B에 도착하지 않게되었다.
 이때쯤 되면 B는 종료하지 못하고(TCP는 소심해서 뭘 하던지 완료 메시지를 받아야 마음을 놓는다) 다시 A에게 한번 더 FIN(SEQ:6001, ACK:5001)을 날린다.
 여기서 A가 TIME_WAIT가 아니라 바로 종료 되어버린 상태 였다면, 이 마지막 FIN 역시 무시했을 테고 B는 여전히 A가 종료 되었는지 살아 있는지 모르고 아둥바둥거리고 있게 될 것이다. 하지만 TIME_WAIT에 있는 A의 소켓은 여전히 주소와 포트를 바인딩 하고 있는 상태이기 때문에 다시 날아 오는 B의 FIN을 감지하고 다시한번 마지막 ACK를 날려 줄 수 있는 것이다.

참 고 :
 열혈강의 TCP/IP 소켓 프로그래밍 : 윤성우
 Unix Network Programming : Stevens

관련 글 :  
 TIME_WAIT state vs SO_REUSEADDR option -> http://kukuta.tistory.com/17