[TCP/IP] TCP 연결 종료와 비정상 종료 4 way handshake (FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT, LAST_ACK, TIME_WAIT)[TCP/IP] TCP 연결 종료와 비정상 종료 4 way handshake (FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT, LAST_ACK, TIME_WAIT)

Posted at 2014.05.23 17:12 | Posted in Network/TCP/IP



facebook에 글올리기



TCP 연결 종료와 비정상 종료 4 way handshake (FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT, LAST_ACK, TIME_WAIT)


TCP 연결을 위해 3 way handshake 를 통해 ESTABLISHED 하는 것과 달리 서로의 연결을 종료할 때는 4 way handshake 를 수행한다.


[TCP/IP] TCP 연결 3 way handshake (SYN, SYN/ACK, ACK)


아무래도 새로 연결을 하는 것보다, 연결되어 있는 상황에서 종료할 때 예기치 못한 상황이 많기 때문에, 확인 과정이 더 까다로운 것 같다.


* 4 way handshake 를 통한 TCP 연결 종료




그림의 4 way handshake 는 아래와 같은 방법으로 이루어진다.

최초에는 서로 통신 상태이기 때문에 양쪽이 ESTABLISHED 상태이다.


1. 통신을 종료하고자 하는 Client가 서버에게 FIN 패킷을 보내고 자신은 FIN_WAIT_1 상태로 대기한다.


2. FIN 패킷을 받은 서버는 해당 포트를 CLOSE_WAIT으로 바꾸고 잘 받았다는 ACK 를 Client에게 전하고 ACK를 받은 Client는 상태를 FIN_WAIT_2로 변경한다.

그와 동시에 Server에서는 해당 포트에 연결되어 있는 Application에게 Close()를 요청한다.


3. Close() 요청을 받은 Application은 종료 프로세스를 진행시켜 최종적으로 close()가 되고 server는 FIN 패킷을 Client에게 전송 후 자신은 LAST_ACK 로 상태를 바꾼다.


4. FIN_WAIT_2 에서 Server가 연결을 종료했다는 신호를 기다리다가 FIN 을 받으면 받았다는 ACK를 Server에 전송하고 자신은 TIME_WAIT 으로 상태를 바꾼다. (TIME_WAIT 에서 일정 시간이 지나면 CLOSED 되게 된다.)

최종 ACK를 받은 서버는 자신의 포트도 CLOSED로 닫게 된다.


현재 포트의 상태는 netstat 명령어를 통해 확인할 수 있다.


netstat 옵션 및 간단 정리


앞에서도 이야기 했듯이, TCP 연결 종료는 연결보다 더 복잡하고 예기치 못한 상황들이 많이 일어난다.


* 비정상 종료 상황


따라서 다양한 상황에 따른 연결의 종료를 적절하게 처리하지 못하면, FIN_WAIT_1, FIN_WAIT_2, CLOSE_WAIT 상태로 남아 계속 기다리는 상황이 올 수 있다.


- CLOSE_WAIT 상태 : 어플리케이션에서 close()를 적절하게 처리해주지 못하면, TCP 포트는 CLOSE_WAIT 상태로 계속 기다리게 된다. 이렇게 CLOSE_WAIT 상태가 statement에 많아지게 되면, Hang 이 걸려 더이상 연결을 하지 못하는 경우가 생기기도 한다. 따라서 어플리케이션 개발시 여러 상황에 따라 close() 처리를 잘 해줘야 한다.


- FIN_WAIT_1 상태 : FIN_WAIT_1 상태라는 것은 상대방측에 커넥션 종료 요청을 했는데, ACK를 받지 못한 상태로 기다리고 있는 것이다. 이것은 아마 서버를 찾을 수 없는 것으로, 네트워크 및 방화벽의 문제일 수 있다.

(FIN_WAIT_1 의 상태는 일정 시간이 지나 Time Out이 되면 자동으로 닫는다.)


- FIN_WAIT_2 상태 : FIN_WAIT_2 상태는 클라이언트가 서버에 종료를 요청한 후 서버에서 요청을 접수했다고 ACK를 받았지만, 서버에서 종료를 완료했다는 FIN 을 받지 못하고 기다리고 있는 상태이다. 이상태는 양방의 두번의 통신이 이루어졌기 때문에 네트워크의 문제는 아닌 것으로 판단되며,(FIN 을 보내는 순간에 순단이 있어 못받은 것일 수도 있다.) 서버측에서 CLOSE를 처리하지 못하는 경우일 수도 있다. FIN_WAIT_2 역시 일정시간 후 Time Out이 되면 스스로 Closed 하게 된다.


- 어떠한 이유에서 FIN_WAIT_1과 FIN_WAIT_2 상태인 연결이 많이 남아있다면, 문제가 발생할 수 있다. 물론 일정 시간이 지나 Time Out이 되면 연결이 자동으로 종료되긴 하지만, 이 Time Out이 길어서 많은 수의 소켓이 늘어만 난다면, 메모리 부족으로 더 이상 소켓을 오픈하지 못하는 경우가 발생한다.

(이 경우는 네트워크나 방화벽 또는 어플리케이션에서 close() 처리 등에 대한 문제등으로 발생할 수 있으며, 원인을 찾기가 쉽지 않다.)

 

- 이러한 문제 해결을 위해서 FIN_WAIT_1과 FIN_WAIT_2 의 Time Out 시간을 적절히 조절할 필요가 있다.


- 각 상태의 Time Out 시간 확인 및 설정은 유닉스 환경에서 ndd 명령어를 통해 확인할 수 있다.


* time_wait 종료 시간 확인 : ndd -get /dev/tcp tcp_time_wait_interval

* time_wait 종료 시간 30초로 설정 : ndd -set /dev/tcp tcp_time_wait_interval 30000


* fin_wait_2 타임 아웃 시간 확인 : ndd -get /dev/tcp tcp_fin_wait_2_timeout

* fin_wait_2 타임 아웃 시간 5분으로 설정 : ndd -set /dev/tcp tcp_fin_wait_2_timeout 300000


ndd 명령어를 통한 다른 상태의 타임아웃 시간 확인 및 설정은 ndd 명령어를 더 찾아봐야 한다.


저작자 표시 비영리 변경 금지
신고
이웃추가
facebook에 글올리기
  1. 잘 배우고 갑니다
    소중한 자료 포스팅하시느라 수고 많으셨습니다
  2. 비밀댓글입니다
  3. 감사합니다 잘보고가요.
    근데 netstat 옵션 및 간단정리 보려니까 링크가 유효하지 않네요.

Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기