개발자공부일기

TCP/IP 흐름제어·혼잡제어·오류제어 본문

CS지식/네트워크

TCP/IP 흐름제어·혼잡제어·오류제어

JavaCPP 2025. 11. 10. 18:44

흐름제어·혼잡제어·오류제어 

네트워크에서 송신자 → 인터넷(라우터들) → 수신자 흐름이 있을 때,

  • 흐름제어: 수신자 보호(버퍼 넘침 방지)
  • 혼잡제어: 네트워크 보호(라우터 큐 과부하 방지)
  • 오류제어: 손상·유실 복구(정확성 보장)

실제 전송 가능량은 보통
실제 송신 윈도 = min(수신자 광고 윈도 rwnd, 혼잡윈도 cwnd)

 

rwnd (receiver window, 수신자가 광고하는 윈도)

  • 수신 측 애플리케이션/커널 버퍼의 남은 여유를 바이트 단위로 광고한 값.
  • 송신자는 아직 ACK로 확인되지 않은 데이터 총량이 rwnd를 넘지 않도록 전송량을 제한한다

cwnd (congestion window, 혼잡 윈도)

  • 송신 측이 네트워크 혼잡을 추정해 스스로 설정하는 전송 한도. 네트워크가 견딜 만한 속도로만 보내려는 자가 규제값.


즉 수신자가 작게 받겠다 하면 그게 한계, 네트워크가 붐비면 그것도 한계가 됨.


1) 흐름제어(Flow Control)


수신자가 처리할 수 있는 속도에 맞춰 송신 속도를 조절해, 수신 버퍼가 넘치지 않게 하는 메커니즘으로

TCP 통신에서 패킷을 송/수신할 때 송신 측에선 송신할 패킷을 TCP 버퍼에 잠시 저장했다 보내고 수신 측에선 수신할 패킷을 바로바로 처리할 수 없으므로 일단 TCP 버퍼에 수신한 패킷들을 저장해 놓는다.

그런데 만약 수신 측의 처리 속도(수신 측 TCP 버퍼가 비는 속도) 보다 송신 측의 패킷 전송량이 많을 경우 전송된 패킷의 일부가 수신 측 TCP 버퍼에 저장되지 못하는 상황이 발생한다. 이 경우 전송된 패킷의 일부가 소실될 수 있다.

 

이런 문제를 막기 위해 흐름제어를 통해 수신 측에서 감당하지 못할 정도의 많은 데이터를 송신 측에서 보내지 않도록 제어하는 것이다.

 

Stop and Wait 방식

매번 전송한 패킷에 대해 확인 응답을 받아야만 그 다음 패킷을 전송하는 방법이다.

 

Stop-and-Wait는 “파이프라인”이 전혀 없음. 데이터를 하나 보내고 응답받고 하기때문에 왕복 지연(RTT)이 크거나 링크가 빠를수록, 대기 시간이 낭비로 커진다. 굉장히 비효율적이다.

 

Sliding Window (Go Back N ARQ)

먼저 window라는게 뭔지부터 설명하고 가겠다.

윈도우는 송/수신 스테이션 양쪽에서 만들어지는 TCP 버퍼의 크기다.

 

네트워크 통신을 할 때 송신 측은 버퍼에 TCP 세그먼트를 보관하고 순차전송하고, 수신 측은 도착한 TCP 세그먼트를 애플리케이션이 읽을 때까지 버퍼에 저장하게 됩니다. 이렇게 일시적으로 TCP 세그먼트를 저장하는 공간이 윈도우입니다.

 

윈도우 크기는 ACK 신호를 보낼 떄 TCP 헤더에 같이 담아 보냄으로써 계속해서 윈도우 크기를 조절하게 된다.

이전에 배웠듯 TCP 헤더에는 Window Size를 저장하는 공간이 존재한다. 따라서 ACK 신호를 받았다면 Window Size에 저장된 값을 파악하여 상대방이 어느 정도의 패킷을 수신할 수 있는지 파악하고 그에 따라 송신할 패킷 양을 조절할 수 있는 것이다. 연결 과정인 3-way Handshake에서는 ACK 신호를 보낼 때 TCP 버퍼가 모두 비어있는 상태일 것이므로 기기의 TCP 버퍼 크기가 곧 윈도우 사이즈가 될 것이다.

 

 

문제는 슬라이딩 윈도우 기법을 사용할 경우 중간에 소실되는 패킷이 존재할 수 있다.

이러한 소실 패킷을 처리하는 방법이 고안돼야 했으며 이 때문에 "오류 제어"라는 TCP 제어 기법이 등장하게 된다.

 


2) 혼잡제어(Congestion Control)


네트워크 내부(라우터 큐)가 붐비지 않게 송신 속도를 스스로 조절하는 메커니즘으로

여러 송신자가 동시에 많이 보내면 라우터 큐가 가득 차고 손실·지연이 폭증한다. 이를 막아 전체 네트워크가 무너지지 않도록 함.

송신자가 네트워크 혼잡의 징후(패킷 손실, 중복 ACK, RTT 증가, ECN 표시 등)를 감지했을 때 작동한다.

 

혼잡 회피 방식

AIMD(Additive Increase Multicative Decrease)

직역하자면 합 증가/곱 감소 알고리즘이다.

 

처음에는 패킷을 1개만 보내고 문제없이 도착했다면 윈도우 크기를 1씩 증가시키며 전송하는 것이다.

만약 전송에 실패했거나 Timeout이 발생할 경우 윈도우 크기를 반으로 줄인 뒤 패킷을 재전송하게 된다.

 

위 사진에서 볼 수 있듯 보내는 패킷이 1부터 시작하여 선형으로 증가하다 6개의 패킷을 보낼 때 전송이 실패하였다면 6의 반인 3으로 윈도우 크기를 줄인 뒤 다시 패킷을 전송하는 것이다.

 

이 방식은 여러 호스트가 1개의 네트워크를 공유하고 있는 경우에도 시간이 지나면 공평하게 패킷을 보낼 수 있다는 장점이 있다.

하지만 윈도우 크기 증가폭이 선형으로 증가하는데 이는 증가폭이 매우 작은 것이다. 따라서 높은 대역폭을 사용하여 효율적인 통신이 진행되기까지 시간이 너무 오래 걸리며 네트워크 혼잡을 미리 감지하는 것이 아닌 혼잡 상황에 닥쳐야지만 대역폭을 줄이는 방식이라는 단점이 존재한다.

 

Slow Start

 

AIMD의 대역폭 증가 폭이 너무 작아 전송 속도 증가 시간이 오래 걸린다는 단점을 보완하기 위해 나온 방식이 Slow Start 방식이다.

 

Slow Start에선 윈도우 크기를 1, 2, 4, 8... 처럼 2배씩 증가시키며 혼잡이 감지될 경우 윈도우 크기를 1로 줄이는 방식이다.

 

Slow Start에서 가장 주의 깊게 봐야 하는 것은 "Threshold(ssthresh)"이다. 이 지점은 "임계값"이라고 하는데 윈도우 크기가 임계값 이상이 될 경우 윈도우 크기가 2배씩 증가하는 것이 아닌 AIMD 방식처럼 1씩 증가하게 된다. 혼잡이 감지될 경우 윈도우 크기가 1이 됨과 동시에 Threshold 값 또한 바뀌게 되는데 이 공식은 그렇게 중요하진 않으므로 따로 설명하진 않겠다.

 

빠른 재전송(Fast Transmit)

빠른 재전송을 알기 위해선 "3-ACK Duplicated"라는 용어를 알아야 한다. 3-ACK Duplicated란 송신 측이 3번 이상 중복된 ACK 신호를 받은 상황을 의미한다.

 

네트워크를 잘 공부했다면 알겠지만 수신 측은 송신 측에서 보낸 패킷이 아닌 수신 측에서 처리한 마지막 패킷에 대하여 ACK 번호를 생성하게 된다.

따라서 만약 중간에 패킷이 소실되었다면 수신 측에서 처리한 마지막 패킷의 번호는 변동되지 않을 것이며 자연스럽게 ACK 번호 또한 변하지 않을 것이다.

즉, 동일한 ACK 신호를 가진 패킷이 여러 번 송신 측으로 보내질 수 있다는 것이다.

 

TCP 통신에서는 송신 측에서 3번이나 동일한 ACK 신호를 받았다면 어떠한 이유로 수신 측이 ACK 신호에 해당하는 패킷 이후의 패킷을 처리하지 못한 것으로 간주한다.

즉, TCP 통신 중 손실이 발생하여 통신 장애가 생겼다고 간주하는 것이다.

 

그렇다면 왜 3번일까?

TCP 통신의 특성상 패킷의 순서가 항상 유지될 것이라는 보장은 없다. 따라서 1~2번의 중복은 패킷의 순서가 뒤죽박죽으로 수신 측에 도착하였다고 생각하여 혼잡 상황으로 간주하지 않는 것이다.

 

3-ACK Duplicated 문제가 발생하여 통신 장애로 인해 송신되지 못한 패킷을 재전송하는 것을 "빠른 재전송"이라고 한다.

혼잡 제어에서는 빠른 재전송이 발생할 경우 혼잡이 발생한 것으로 간주하여 윈도우 사이즈를 절반으로 줄인다.

 

빠른 회복(Fast Recovery)

혼잡한 상태가 될 경우 윈도우 사이즈를 1로 줄이는 것이 아닌 절반으로 줄인 뒤 선형 증가시키는 방식이다.

빠른 회복 정책이 적용되었다면 혼잡 상황을 한 번 겪은 뒤 순수 AIMD 방식으로 동작하게 된다.


3) 오류제어(Error Control)


전송 중 생기는 비트 오류·프레임 손상·패킷 유실을 검출하고, 필요한 경우 재전송 또는 추가 정보로 복구하는 메커니즘이다.

무선·장거리·붐빈 구간 등에서는 손상/유실이 빈번하다. 그대로 두면 애플리케이션이 깨진 데이터를 받게 된다.

데이터 무결성 검사가 실패했을 때(체크섬/CRC 불일치), 또는 수신 확인(ACK)이 오지 않아 유실이 의심될 때 작동한다.

 

어떻게 이루어지나(과정)

  1. 수신 측이 데이터 무결성을 검사한다(체크섬/CRC).
  2. 이상이 없으면 ACK(정상 수신 알림)를 보내고, 송신자는 해당 데이터의 전송을 확정한다.
  3. 이상이 있거나 일정 시간 안에 ACK가 없으면, 송신자는 해당 데이터를 재전송한다(ARQ).
  4. 선택적 확인(SACK 등)을 활용하면 잃어버린 조각만 골라 재전송하여 낭비를 줄일 수 있다.
  5. 환경에 따라 추가적인 오류정정 코드(FEC)를 실어, 재전송 없이도 일부 오류를 수신 측에서 스스로 복구하기도 한다.

 

오류 검출 방식

 

송신 측이 ACK 신호를 받지 못함

데이터를 송신한 측이 ACK 신호를 받지 못했다는 것은 두 상황 중 하나이다.

송신한 패킷이 통신 중 소실되었거나, 패킷이 정상적으로 처리되어 수신 측이 ACK 신호를 보냈지만 ACK 신호가 중간에 소실된 경우이다. 후자의 경우 사실 수신 측에선 패킷을 받은 상태이므로 다시 보내지 않아도 된다.

하지만 TCP 통신 과정에서 전자의 이유로 ACK 신호가 안온 것인지 후자의 이유로 안 온 것인지 파악할 수 없으므로 오류라고 간주하는 것이다.

 

중복된 ACK를 받음(3 ACK Duplicated)

이는 아래 혼잡 제어를 설명할 때 자세히 설명할 것이다.

지금 간단히 말하자면 동일한 ACK 번호를 가진 패킷을 3번 이상 받으면 패킷이 정상적으로 송신되지 않았다고 판단하는 것이다.

 

수신 측이 NAK 신호를 보냄

ACK의 반대되는 신호로 NAK라는 신호가 존재한다.

이 신호 또한 TCP 헤더에 저장된 값으로 수신 측에서 특정 패킷이 도착하지 않았으므로 해당 패킷을 다시 보내달라고 NAK를 통해 요청하는 것이다.

 

하지만 ACK 만으로도 오류 검출이 충분히 가능하기 때문에 사용하지 않는 경우도 있다.

 

 

 

Stop and Wait ARQ

만약 송신지에서 ACK 신호를 받지 못했다고 가정하자. 그럼 ACK 신호가 소실되었든 송신 패킷이 소실되었든 TCP 통신상 문제가 발생한 것이다.

 

이 경우 ACK 신호를 일정 시간이 지나도 받지 못하면 Timeout이 발생했다고 판단하여 오류가 발생했다고 인지한다.

그럼 송신지에서는 이전에 보낸 패킷을 다시 보냄으로써 오류 검출 및 재전송을 수행하는 것이다.

 

이 Timeout 은 너무 길어도 좋지 않고 너무 짧아도 좋지 않으므로 적절한 시간을 찾는 것이 중요하다.

 

이를 위해 타임아웃 대기 시간을 특정 값으로 고정하지 않고 네트워크 상황에 따라 동적으로 변경하는 방법을 취하고 있는데 ACK 번호가 돌아오는 시간을 기준으로 이를 판단하게 된다

 

데이터를 송신할 때 ACK 번호가 돌아오는 시간을 계측하고 만약 ACK 번호가 돌아오는 시간이 지연되면 이에 따라 대기 시간을 늘리며 지정된 시간보다 빠르게 도착하면 다시 대기 시간을 짧게 만드는 방식이다.

 

타임아웃의 최솟값은 0.5~1초로 지정되어 있다.

 

 

Go-Back-N ARQ(GBN)

연속으로 패킷을 보내다 오류가 발생했다고 판단되는 지점 이후의 모든 프레임을 재전송하는 오류 제어 방식이다.

 

수신 측에서는 정상적으로 받지 못한 패킷이 있을 경우 해당 패킷의 다음 패킷들을 받았다 하더라도 문제가 되는 패킷의 직전 패킷에 대한 ACK를 보낸다.

 

송신 측에서 0 ~ 5까지의 패킷을 전송하려고 하고있다.

송신자는 순서대로 0,1,2,3,4,5를 보냈고 0,1에 대한 ACK는 받았으나 2번 패킷의 타임아웃 타이머가 지날때까지 수신자로부터 ACK를 받지 못했다.

 

수신자는 소실된 2번 패킷부터 3,4,5를 폐기한다. 송신자는 타임아웃된 2번 패킷부터 재전송을 실시한다..

 

GBN은 송신지에서 전송한 패킷 중 ACK 신호가 돌아오지 않은 가장 최신 패킷에 대해 타이머를 설정한다.

만약 타이머가 만료될 때까지 ACK 신호가 오지 않는다면 해당 패킷부터 전송한 모든 패킷에 대하여 재전송을 시행하는 것이다.

만약 ACK 신호가 정상적으로 도착했다면 다음 전송한 패킷에 대하여 다시 타이머가 설정될 것이다.

 

따라서 일정 시간이 지나 2번 패킷에 대하여 Time out이 발생했다면 2번 패킷 이후의 모든 패킷, 즉 2,3,4,5 패킷을 재전송하게 되는 것이다. 분명 0, 1 패킷이 정상적으로 도착했다는 것을 송신 측에서 인지하였고 이후에 2, 3, 4 패킷을 보낸 것임에도 불구하고 2번 패킷이 정상적으로 도착하지 않았다는 이유만으로 2, 3, 4, 5패킷이 다시 재전송되는 것이다.

 

추가로 송신 측에서 재전송을 했는데 수신 측 버퍼에 남아있는 공간이 없는 경우였다면 재전송 패킷 때문에 네트워크가 혼잡해질 수 있다. 송신 측은 계속해서 데이터를 보낼 것이고 수신 측은 버퍼에 공간이 없으니 받은 데이터를 계속 폐기할 것이므로 쓸모없는 패킷의 흐름이 생기는 것이다.

 

따라서 수신 측에서 ACK를 보내며 남은 TCP 버퍼의 크기(윈도우 크기)를 같이 보내줘 송신 측에 알리게 된다.

 

 

 

Selective-Reject(SR) ARQ

GBN ARQ의 가장 큰 단점은 확인된 마지막 프레임 이후의 모든 프레임을 재전송해야 한다는 점이다.

 

위 이미지에서 볼 수 있듯 2번 패킷에 대한 ACK 신호가 오지 않았다는 이유로 재전송돼야 하며 이는 네트워크에 흐르는 패킷의 양을 증가시킬 것이다.

 

이러한 문제점을 해결하기 위해 손상되거나 소실된 패킷만 재전송하는 것이 SR ARQ 방식이다.

 

소실된 패킷만 재전송하면 되므로 네트워크에 흐르는 패킷을 최소화시킬 수 있기 때문에 장점만 있어 보이지만 SR ARQ에는 큰 약점이 존재한다.

 

TCP 통신에서는 패킷이 순서대로 도착한다는 것이 보장되지 않는다는 점 때문에 생기는 문제점이다.

 

SR ARQ는 어떤 패킷이 도착하지 않았는지 알아야 하며 이 때문에 수신 측 버퍼의 데이터가 순차적으로 정렬되어야 할 필요가 있다.

 

GBN의 경우 1, 2, 5, 4로 도착했다 하더라도 4,5 패킷이 폐기되므로 별 문제가 없지만 SR ARQ에서는 1, 2, 5, 4를 1, 2, 4, 5로 정렬하여 3번 패킷이 오지 않았음을 파악하고 3번 패킷만 재전송을 요청해야 한다.

 

따라서 정렬의 과정이 추가로 필요하며 이를 위한 별도의 버퍼가 필요하다. 즉, 비용이 증가하는 것이다.

 


빠른 비교 표

 

항목  흐름제어  혼잡제어  오류제어
목적 수신자 버퍼 보호 네트워크(라우터 큐) 보호 데이터 정확성 보장
신호 수신자 윈도 광고(rwnd) 손실·지연·ECN 등 혼잡 징후 체크섬/CRC, ACK/NAK, 타이머
동작 송신량을 수신자 여유에 맞춰 제한 상황 보며 점진 증가·손실 시 급감 손상·유실 검출 후 재전송/정정
주 위치 전송 계층(TCP) 등 전송 계층(TCP) 링크·전송 계층
한 줄 요약 받는 쪽이 감당할 만큼만 보내라 망이 버틸 만큼만 보내라 틀린 건 잡아내고 바로잡아라

 

'CS지식 > 네트워크' 카테고리의 다른 글

IP란?  (0) 2025.11.05
SSR/CSR/SSG/ISR  (0) 2025.10.20
TCP와 UDP  (0) 2025.02.25