CS/네트워크

TCP연결이 갑자기 끊기면 어떻게 될까? = 유령 세션

Junuuu 2022. 5. 17. 22:40

TCP와 네트워크에 대해 잘 모르신다면 다음 글을 읽고 오시면 좋습니다.

https://junuuu.tistory.com/259

 

OSI 7계층이란?

OSI 7 계층이란?(What) Open System Interconnection의 약자로 간단하게 "서로 다른 제조사 시스템 간의 호환성 해결"을 위해 ISO 국제표준 국가에 의해 재정되었습니다. 네트워크에서 통신이 일어나는 과정

junuuu.tistory.com

 

유령 세션이란?

서버에 연결된 클라이언트 세션이 제대로 연결해제 되지 않고 남아 있는 상태를 유령 세션이라고 합니다.

접속 해제에 대한 감지가 이루어지지 않았기 때문에 할당된 리소스 등이 해제되지 않고, 재접속 시 문제를 일으킬 수 있습니다.

 

유령 세션이 발생하는 이유

일반적인 TCP 흐름은 다음과 같습니다.

 

클라이언트와 서버의 연결을 위한 3-way handshaking

https://terms.naver.com/entry.naver?docId=3431875&cid=58437&categoryId=58437&expCategoryId=58437

클라이언트와 서버의 해제를 위한 4-way handshaking

https://terms.naver.com/entry.naver?docId=3431875&cid=58437&categoryId=58437&expCategoryId=58437

이때 클라이언트 세션을 바로 종료하지 않고 Wait 상태에 돌입하는 이유는 서버가 FIN을 보내기 전에 전송한 패킷이 아직 도착하지 않은 경우를 대비하기 위해서입니다.

 

위의 방법은 매우 합리적으로 보이지만 실제 네트워크 현실은 그렇게 합리적으로 작동하지 않습니다.

 

만약 Establish 상태의 클라이언트가 closesocket()이나 shutdown()을 통해 FIN 패킷을 전송하지 못한 채로 네트워크 연결이 단절되는 경우가 일어날 수 있습니다.

 

서버와 클라이언트는 모두 자신이 ESTABLISH 상태에 있다고 인지하고 상대의 ACK를 기다리거나 Time out되어 재전송 또는 재전송 요청을 반복하게 됩니다.

 

 

해결 방법

  • 응답에 대한 Time out을 걸어놓자

만약 서버와 클라이언트가 연결이 필요하지만 아무 요청도 전송도 일어나지 않은 상황이 발생한다면 연결이 비정상 종료되므로 이 방법으로는 해결이 어려워 보입니다.

  • 지속적으로 연결을 확인하는 패킷을 전송하자

일정시간동안 데이터나 ACK 패킷이 오지 않으면 keep-alive 패킷을 보내 연결이 계속 이루어지고 있는지 확인하는 방법입니다.

  • Linger 옵션 사용

Linger 옵션은 소켓 종료 함수를 호출했을 때 아직 송신되지 않고 송신 버퍼에 남아있는 데이터를 어떻게 처리하는지 OS에 알려주는 옵션입니다.

 

옵션을 3가지 방법이 있습니다.

 

1) ling.l_onoff = 1, ling.l_linger = 0

closesocket() 함수는 즉시 반환, 버퍼에 남은 데이터는 버림. 

강제 종료(abortive shutdown) 처리. TIME_WAIT가 남지 않음.

 

2) ling.l_onoff = 1, ling.l_linger != 0

blocking 방식의 정상 종료(graceful shutdown)처리

 

3) ling.l_onoff = 0 

non-blocking 방식의 정상적 종료 처리. 종료 처리가 완결된 시점을 알 수는 없다.

 

 


여기서 TIME_WAIT는 종료 시 잔여 패킷이 제대로 전달되기 위해서 필요한 단계입니다.

이 단계를 어떻게 처리하느냐에 따라 이슈가 발생할 수 있습니다.

종료시킨 소켓에서 TIME_WAIT 상태가 2분 이상 지속되기 때문입니다.

 

만약 서버에서 각 클라이언트 세션의 소켓에게 closesocket()을 호출한다고 가정해보겠습니다.

그러면 클라이언트 세션 소켓 하나마다 2분의 TIME_WAIT 단계를 거쳐야 하며 이는 리소스 낭비로 이어지고 장애 발생의 원인이 됩니다.

 

즉, 클라이언트 세션을 종료시키는 서버의 경우 TIME_WAIT을 남기지 않는 1번 방법을 사용하는 것이 좋습니다.

 

 

Graceful Shutdown

우아한 종료? 깔끔한 종료?라고 불립니다.

 

일반적인 종료의 순서를 따르는 것이 우아한 종료입니다.

위에서 봤던 4-way-handshake라 불리는 정상적인 종료의 순서를 따릅니다.

Time_WAIT 단계를 부정적으로 이야기하는 사람들도 있지만, 이 단계 또한 데이터의 손실 없이 올바르게 종료할 수 있도록 필요한 단계입니다.

 

Graceful Shutdown을 위해서는 클라이언트가 먼저 closesocket()을 호출해야 합니다.

Linger 옵션에서 정리했던 것처럼 서버에서 closesocket()을 호출하면 TIME_WAIT로 남아있는 세션들 때문에 리소스를 낭비하게 됩니다.

 

이를 해결하기 위해서 강제 종료시킬 순 있지만 이는 우아한 종료라고 말하기 힘듭니다.

 

 

출처

https://ozt88.tistory.com/19

 

TCP의 연결 종료

TCP의 단절 감지 : 유령 세션 1. 유령 세션이란? 서버에 연결된 클라이언트 세션이 네트워크 단절되었는데도 제대로 연결해제가 되지 않아서 그대로 남아있는 상태를 유령세션이라고 한다. 제대

ozt88.tistory.com

https://terms.naver.com/entry.naver?docId=3431875&cid=58437&categoryId=58437&expCategoryId=58437

 

전송 계층(4계층)

4계층인 전송 계층은 양 끝단(End to end)의 사용자들이 신뢰성 있는 데이터를 주고받을 수 있도록 함으로써, 상위 계층들이 데이터 전달의 유효성이나 효율성을 신경 쓰지 않도록 해준다. 전송 계

terms.naver.com

 https://unsigned.tistory.com/16

 

TCP 유령세션

1. 유령 세션이란? 서버에 연결된 클라이언트 세션이 네트워크 단절되었는데도 제대로 연결해제가 되지 않아서 그대로 남아있는 상태를 유령세션이라고 한다. 제대로 접속해제가 되지 않았기

unsigned.tistory.com