[Network] TCP/IP 흐름제어 & 혼잡제어

미누·2024년 3월 6일

CS_네트워크

목록 보기
4/8

TCP는 크게 3가지 제어 기능이 있다.

  • 전송되는 데이터의 양을 조절하는 흐름 제어
  • 데이터가 유실되거나 잘못된 데이터가 수신되었을 경우 대처하는 방법인 오류 제어
  • 네트워크 혼잡에 대처하는 혼잡 제어

이 기능들 덕분에 예외 상황에 크게 신경쓰지 않고 상위 레이어 동작에 집중할 수 있다.

✅ 흐름 제어

송신 측과 수신 측의 데이터 처리 속도가 다를 수 있다.
송신 측이 빠를 때 수신 측 버퍼가 넘치는 오버플로우 문제가 발생한다.
이러한 문제를 줄이기 위해 윈도우 크기로 송신 측의 데이터 전송량을 조절한다.
  • 윈도우 크기 : 자신이 처리할 수 있는 데이터의 양

📌 stop and wait

상대방에게 데이터를 보낸 후 잘 받았다는 응답이 올 때까지 기다리는 방식

Stop and Wait로 흐름 제어를 할 경우의 대원칙은 단순히 상대방이 응답을 하면 데이터를 보낸다이기 때문에 구현 자체도 간단하고 개발자가 어플리케이션의 작동 원리를 파악하기도 쉬운 편이다.
하지만 서로 처리 가능, 처리 불가능 정도의 의미만 주고받는 방식은 간단한만큼 비효율적이라고 할 수도 있다. 왜냐하면 송신 측은 자신이 직접 데이터를 보내봐야 이 데이터를 수신 측이 처리할 수 있는지 알 수 있기 때문이다. 쉽게 말해서 이런 기초적인 Stop and Wait 방식은 그냥 될 때까지 주구장창 보내는 방식이라고 봐도 무방하다.

📌 sliding winodw

방금 알아본 바와 같이 Stop and Wait를 사용하여 흐름 제어를 하게 되면 비효율적인 부분이 있기 때문에, 오늘날의 TCP는 특별한 경우가 아닌 이상 대부분 슬라이딩 윈도우(Sliding Window) 방식을 사용한다.

슬라이딩 윈도우는 수신 측이 한 번에 처리할 수 있는 데이터를 정해놓고 그때그때 수신 측의 데이터 처리 상황을 송신 측에 알려줘서 데이터의 흐름을 제어하는 방식이다.

Stop and Wait과 여러 가지 차이점이 있겠지만, 사실 가장 큰 차이점은 송신 측이 수신 측이 처리할 수 있는 데이터의 양을 알고 있다는 점이다. 이 정보를 알고 있기 때문에 굳이 수신 측이 처리 가능이라는 대답을 일일히 해주지 않아도 데이터를 보내기 전에 이게 처리될 지 어떨지 어느 정도 예측이 가능하다는 말이다.

💡 윈도우 크기

최초의 윈도우 크기는 호스트들의 '3 way handshake'을 통해 수신 측 윈도우 크기로 설정되며, 이후 수신 측의 버퍼에 남아있는 공간에 따라 변한다. 윈도우 크기는 수신 측에서 송신 측으로 확인 응답(ACK)을 보낼 때 TCP 헤더(window size)에 담아서 보낸다. 즉, 윈도우는 메모리 버퍼의 일정 영역이라고 생각하면 된다

⚙️ 동작 방식

윈도우에 포함된 패킷을 계속 전송하고, 수신 측으로부터 확인 응답(ACK)이 오면 윈도우를 옆으로 옮겨 다음 패킷들을 전송한다.

먼저, 송신 측이 0 ~ 6번의 시퀀스 번호를 가진 데이터를 상대방에게 전송하고 싶어하는 상황을 상상해보자. 이때 송신 측의 버퍼에는 전송해야할 데이터들이 이렇게 담겨져 있을 것이다.


이때 송신 측은 수신 측에게 받은 윈도우 크기와 현재 네트워크 상황을 고려하여 윈도우 크기를 3으로 잡았고, 윈도우 안에 있는 데이터를 우선 주르륵 전송한다.

이때 윈도우 안에 들어있는 데이터는 어떤 상태일까? 일단 데이터를 전송하기는 했지만 아직 수신 측으로부터 잘 받았다는 응답을 받지 못한 상태일 것이다.

즉, 윈도우에 들어있는 데이터들은 항상 전송은 했지만, 상대방이 처리했는지는 모르는 상태라고 할 수 있다. 물론 데이터를 윈도우에 넣고 나서 블록킹이 걸려 데이터를 처리하지 못하는 상태도 존재할 수 있지만, 그런 것까지 다 고려하면 너무 복잡하니까 간단하게 생각하도록 하자.

이후 수신 측은 자신의 처리 속도에 맞게 데이터를 처리한 후 응답으로 현재 자신의 버퍼에 남아있는 공간의 크기를 알려준다. 만약 수신 측이 응답으로 Window Size: 1을 보냈다면 “내 버퍼 공간이 1 byte만큼 남았으니까 그 만큼만 더 보내봐”라는 의미가 된다.


이때 윈도우를 옆으로 이동시키며 새로 들어온 데이터를 전송하기 때문에 슬라이딩 윈도우라고 하는 것이다. 만약 수신 측이 윈도우 크기를 1이 아니라 더 큰 수를 보냈다면, 송신 측은 그 만큼 윈도우를 옆으로 밀고 더 많은 데이터를 연속적으로 전송할 수 있을 것이다.

단, 이 경우 송신 측의 윈도우 크기가 3이기 때문에 수신 측이 4를 보냈다고 해서 4칸을 밀지는 않고, 자신의 윈도우 크기인 3만큼만 밀 수 있다. 그러나 이 경우에는 송신 측이 수신 측의 퍼포먼스가 더 좋아졌다는 것을 알았으니 자신의 윈도우 크기를 늘리는 방법으로 대처할 수 있을 것이다.

이제 송신 측은 자신이 데이터 한 개를 더 보낼 수 있다는 사실을 알았으니, 자신의 윈도우를 한 칸 옆으로 밀고 새롭게 윈도우에 들어온 3번 데이터를 수신 측에게 전송한다.

이렇게 데이터를 전송하는 송신 측의 버퍼는 대략 3가지 상태로 나눠질 수 있다.

즉 슬라이딩 윈도우 방식은 보내고 -> 응답받고 -> 윈도우 밀고를 반복하면서, 현재 자신이 보낼 수 있는 데이터를 최대한 연속적으로 보내는 방법이라고 할 수 있다
이렇게 슬라이딩 윈도우 방식은 일일히 하나 보내고, 응답 받고 하는 Stop and Wait보다 확실히 전송 속도 측면에서 빠르기도 하고, 송신 측과 수신 측의 지속적인 커뮤니케이션을 통해 윈도우 크기 또한 유연하게 조절할 수 있기 때문에 최근의 TCP에서는 기본적으로 슬라이딩 윈도우를 사용하여 흐름 제어를 하고 있다.

✅ 혼잡 제어

데이터의 양이 라우터가 처리할 수 있는 양을 초과하면 초과된 데이터는 라우터가 처리하지 못한다. 이때 송신 측에서는 라우터가 처리하지 못한 데이터를 손실 데이터로 간주하고 계속 재전송하여 네트워크를 혼잡하게 한다. 이런 상황은 송신 측의 전송 속도를 적절히 조절하여 예방할 수 있는데, 이것을 혼잡 제어라고 한다.

정리하자면, 제어는 송 수신 측 사이의 패킷 수를 제어하는 기능이라 할 수 있으며, 혼잡 제어는 네트워크 내의 패킷 수를 조절하여 네트워크의 오버플로우를 방지하는 기능이다.

혼잡 제어 기법

AIMD (Additive Increse/Multicative Decrease)

우리 말로 직역하면 합 증가/곱 감소 방식이다. AIMD 방식은 처음에 패킷을 하나씩 보내고 문제 없이 도착하면 윈도우의 크기를 1씩 증가시켜가며 전송한다.
만약, 전송에 실패하면 윈도우 크기를 반으로 줄인다. 윈도우 크기를 너무 조금씩 늘리기 때문에 네트워크의 모든 대역을 활용하여 제대로 된 속도로 통신하기까지 시간이 오래 걸린다는 단점이 있다.

Slow Start (느린 시작)

위에서 이야기했듯이 AIMD 방식은 윈도우 크기를 선형적으로 증가시키기 때문에, 제대로된 속도가 나오기까지 시간이 오래 걸린다. 반면, Slow Start는 윈도우의 크기를 1, 2, 4, 8, ...과 같이 지수적으로 증가시키다가 혼잡이 감지되면 윈도우 크기를 1로 줄이는 방식이다.
이 방식은 보낸 데이터의 ACK가 도착할 때마다 윈도우 크기를 증가시키기 때문에 처음에는 윈도우 크기가 조금 느리게 증가할지라도, 시간이 가면 갈수록 윈도우 크기가 점점 빠르게 증가한다는 장점이 있다.

빠른 재전송 (Fast Retransmit)

  • TCP는 지금가지 받은 데이터 중 연속되는 패킷의 마지막 순번 이후를 ACK 패킷에 실어서 보낸다.
  • 그래서 송신 측이 아래처럼 3, 4번을 보내더라도 ACK 2 를 중복해서 받는다.
  • 그러면 timeout이 발생하기 전이라도 송신 측은 문제가 되는 2번 패킷을 재전송한다.
  • 3 ACK Duplicated : 송신 측이 3번 이상 중복된 ACK 번호를 받은 상황
  • 그리고 혼잡한 상황이라고 판단해서 윈도우 크기를 줄인다.

빠른 회복 (Fast Recovery)

빠른 회복은 혼잡한 상태가 되면 윈도우 크기를 1로 줄이지 않고 반으로 줄이고 선형 증가시키는 방법이다. 이 방법을 적용하면 혼잡 상황을 한 번 겪고나서부터는 AIMD 방식으로 동작한다.

참고

https://evan-moon.github.io/2019/11/22/tcp-flow-control-error-control/
https://evan-moon.github.io/2019/11/26/tcp-congestion-control/#aimd
https://steady-coding.tistory.com/507

0개의 댓글