데이터 보내기를 완료했을 때 연결을 끊는다.
애플리케이션이 송신해야 하는 데이터를 송신 완료했다고 판단하면 송/수신을 종료한다. 이때, 어디에서 송/수신을 종료하는지는 애플리케이션마다 다르다. 웹의 경우 서버가 요청에 대한 응답을 보내면 완료로 간주하고 서버 측에서 끊기에 들어간다. 구체적인 동작 과정은 다음과 같다.
1.FIN: 1
서버 측 애플리케이션이 먼저 Socket 라이브러리의 close를 호출한다. 그러면 서버 측 프로토콜 스택이 TCP 헤더를 만들고, 이 헤더의 FIN 컨트롤 비트를 1로 설정한다. 그 후 IP에 의뢰해 클라이언트에 송신을 한다. 서버 측 소켓에 연결 끊기 동작에 들어갔다는 정보도 기록한다.
2. ACK 번호
FIN을 1로 설정한 TCP 헤더가 도착하면, 클라이언트 프로토콜 스택은 자신의 소켓에 서버 측이 연결 끊기 동작에 들어갔다는 것을 기록한다. 그 후 패킷을 받았다는 것을 알리기 위해 ACK 번호를 서버 측에 반송하고 애플리케이션이 데이터를 가져올 때까지 대기한다.
3. FIN: 1
이제 애플리케이션이 read를 호출해 데이터를 가져올려 하면, 데이터를 건네는 대신 서버에서 보낸 데이터를 모두 수신 완료했다는 사실을 알린다. 웹은 응답을 반송하면 끝나므로 이제 클라이언트도 종료한다. 이제 클라이언트 애플리케이션도 close를 호출한다. 그러면 크라이언트 프로토콜 스택이 FIN 컨트롤 비트를 1로 만든 TCP 헤더를 만들고 IP에 의뢰해 송신한다.
4. ACK 번호
서버에 ACK 번호가 돌아오면 서버와의 대화가 끝난다.
소켓을 말소한다
위 과정을 통해 서버와의 통신이 끝나면 소켓은 필요없게 된다. 그럼에도 소켓을 바로 말소시키지 않고 잠시 기다린다. 소켓을 바로 말소시키지 않는 이유는 오동작을 막기 위함이다. 오동작이 발생하는 이유는 다양하므로 한 가지 예만 들어보자. 다음과 같은 과정으로 끊기 동작이 발생한다 해보자.
1. 클라이언트가 FIN 송신
2. 서버가 ACK 번호 송신
3. 서버가 FIN 송신
4. 클라이언트가 ACK 번호 송신
위 경우 서버는 ACK 번호가 돌아오지않아 다시 FIN을 보낼 수 있다. 이때 기존 소켓이 말소되고 다른 애플리케이션이 새로운 소켓을 작성하면, 같은 포트 번호가 할당될 수 있다. 이 상황에서 FIN이 도착하면 새 소켓이 연결 끊기 동작에 들어간다.
패킷을 다시 보내는 동작과도 연관있다. 패킷이 없어지면 보통 몇 분 정도 다시 보내는 동작을 하고 그 시간이 경과하면 다시 보내는 동작을 중단한다. 이 기간 동안엔 다시 보낸 패킷이 네트워크에 존재할 가능성이 있으므로 다시 보내기 동작이 완전히 끝나기를 기다린다. 이 기간은 보통 몇 분 정도이다.
출처 - 성공과 실패를 결정하는 1%의 네트워크 원리