TCP는 송수신을 수행하기 전 연결을 수립하고, 송수신이 끝나면 연결을 종료한다. 그리고 데이터를 송수신 할 때에는 신뢰성 있는 데이터를 보장하기 위해 재전송을 통한 오류 제어, 흐름 제어, 혼잡 제어를 보장해준다
재전송 기반 오류 제어
TCP 세그먼트에는 오류를 검출하기 위한 체크섬 필드가 있는데, 이걸로는 충분하지 않다. 왜냐하면, 체크섬 필드는 '데이터 훼손 여부'에만 관심이 있지 패킷 자체의 유실 여부, 전송 오류 등에 대한 것은 관심이 없다.. 때문에 TCP가 신뢰성을 제대로 보장하려면 다음이 보장되어야 한다.
- 송신 호스트가 송신한 세그먼트에 문제가 발생했음을 인지할 수 있어야 함
- 오류를 감지하게 되면 해당 세그먼트를 재전송할 수 있어야 함
그렇다면 TCP는 언제 오류를 검출하고 재전송할까?
- 중복된 ACK 세그먼트 수신
- 중간에 세그먼트가 유실되었다는 의미
- 타임아웃 발생
- 호스트가 세그먼트를 전송할 때마다 '재전송 타이머(retransmission timer)' 시작
- 타임아웃이 발생할 때까지 ACK 세그먼트를 받지 못하면 유실되었다고 가정하고 재전송
재전송 기법: ARQ(Automatic Repeat Request, 자동 재전송 요구)
수신 호스트의 답변(ACK)과 타임아웃을 토대로 문제를 진단하고, 문제가 생긴 메시지를 재전송함으로써 신뢰성을 확보하는 방식이다. ARQ를 사용하는 프로토콜이나 계층은 여러가지가 있을 수 있지만 그중 대표적인 것이 전송(Transport) 계층의 TCP이다.
- ARQ의 대표적인 세 가지 방식
- Stop-and-Wait ARQ
- Go-Back-N ARQ
- Selective Repeat ARQ
Stop-and-Wait ARQ
제대로 전송했음을 확인하기 전까지는 새로운 메시지를 보내지 않는 방식이다. '송신->확인' 과정을 단순히 반복해나가는 방식이라고 볼 수 있다. 송신측 호스트는 확인 응답을 받기 전에는 더 보내고 싶어도 못 보내고, 수신측 호스트는 더 많은 데이터를 처리할 수 있어도 하나씩만 응답해야 한다.
만약, Stop-and-Wait ARQ 하에서 어떤 세그먼트가 잘못 전송되었다면, 제대로 전달했음을 확인하기 전까지는 새로운 메시지를 보내지 않기 때문에 당연히 '타임아웃'이 발생할 것이다. 그러면 송신측에서는 다시 세그먼트를 전송할 것이다.
- 장점: 단순하지만, 높은 신뢰성 보장
- 단점: 네트워크의 이용 효율이 낮아지고 성능이 저하 (한번에 무조건 하나씩만 보내야 하니 효율이 안 나옴)
그렇다면 Stop-and-Wait ARQ의 단점을 어떻게 해결할 수 있을까?
간단하다. 각 세그먼트에 대한 ACK 세그먼트가 도착하기 전이더라도 여러 세그먼트를 보낼 수 있어야 한. 그리고 이러한 전송기법을 파이프라이닝(Pipelining)
이라고 한다. 파이프라이닝은 연속해서 메시지를 전송할 수 있는 기술로, n번 세그먼트에 대한 확인 응답이 오기 전이더라도, 연속해서 데이터를 보낼 수 있으니 n + 1번과 n + 2번 세그먼트를 보낼 수 있도록 하게 하는 것이다.
이후 배울 ARQ 기법들은 모두 이러한 파이프라이닝을 기반으로 하고 있다.
Go-Back-N ARQ
파이프라이닝 기반 ARQ의 일종으로, 여러 세그먼트 전송 중 오류가 발생하면 해당 세그먼트부터 전부 재전송하는 기법이다.
만약 송신 측이 파이프라이닝을 통해 n ~ n + 3번 세그먼트를 연속해서 보냈는데, 중간에 n + 2번 세그먼트가 손실되었다고 가정하자. 그렇다면 n + 2번 세그먼트에 대해서 타임아웃이 발생할 것이기에, 수신 측에서는 n + 3번 세그먼트를 받았다고 하더라도 해당 세그먼트를 폐기하고 문제가 발생한 n + 2번 세그먼트부터 다시 시작하는 것이다. 위 그림을 확인해보면, Frame 2만 손실된 상황이다.
이렇게, Go-Back-N ARQ는 순서 번호 n번에 대한 ACK 세그먼트는 'n번만의' 확인 응답이 아닌 'n번까지의 누적 확인 응답'을 의미하게 된다. 그래서 Go-Back-N ARQ의 확인 응답 번호를 '누적 확인 응답(CACK, Cumulative Acknowledgement)'라고 부른다.
하지만,문제 세그먼트 이후 모든 세그먼트를 재전송하므로, 손실된 세그먼트 하나로 인해 이미 성공적으로 도달한 후속 데이터까지 다시 보내야 하는 비효율성으로 인해 네트워크 대역폭 낭비이 낭비된다는 문제가 있다..
Selective Repeat ARQ
Selective Repeat ARQ는 Go-Back-N ARQ의 의 확인된 마지막 프레임 이후의 모든 프레임을 재전송하는 단점을 보완하는 기법으로, 어떤 세그먼트에 대해 확인 응답 번호가 누락되었다면 '해당 세그먼트에 대해서만' 확인 응답 번호를 보내주는 방식이다. 즉, 손상되거나 손실된 프레임만 재전송하는 방식이다. 때문에 별도의 '데이터 재정렬'을 수행해야 하며, 수신 측에 별도의 버퍼를 두어 데이터 재정렬을 수행한다.
위 그림에서 Frame 0 ~ Frame 3까지 파이프라이닝 기법으로 연속해서 보내고 있는데 Frame 2가 손실된 상황이다. 이때 Go-Back-N ARQ를 사용 중이었다면 Frame 2 이후의 모든 세그먼트는 폐기되었겠지만, Selective Repeat ARQ는 이후 세그먼트를 폐기시키지 않고, 손실된 Frame 2에 대해서만 Duplicate ACK를 발생시킨다.
Go-Back-N ARQ에서의 ACK 세그먼트가 '누적 확인 응답'이라면, Selective Repeat ARQ의 ACK 세그먼트는 '개별 확인 응답(Selective Acknowledge)'라고 한다.
오늘날의 대부분의 호스트는 Selective Repeat ARQ를 지원한다. (Selective Repeat ARQ를 사용하지 않을 경우에는 Go-Back-N ARQ로 동작한다)
흐름 제어(Flow Control)
파이프라이닝 기반의 송수신은 한 번에 여러 세그먼트를 보내고 여러 세그먼트에 대한 확인 응답을 받을 수 있는 방식이었다.
그렇다면 한 번에 무한히 많은 데이터를 보내고 받을 수 있을까?
-> 불가능하다!
호스트가 한 번에 받아 처리할 수 있는 세그먼트의 양에는 한계가 있기 때문에 수신 호스트가 한 번에 얼마나 받아 처리할 수 있는지에 대해 반드시 고려해야 한다. 수신 호스트가 한 번에 처리할 수 있는 만큼만 세그먼트를 보내는 것을 '흐름 제어'라고 한다.
TCP의 흐름 제어
- 송신 호스트가 수신 호스트의 처리 속도를 고려하며 송수신 속도를 균일하게 유지하는 기능
- Stop-and-Wait ARQ를 사용하면 별도의 흐름 제어가 필요하지 않다 (파이프라이닝 기법을 사용하지 않기 때문)
- 파이프라이닝 기반의 Go-Back-N ARQ와 Selective Repeat ARQ에서는 흐름 제어가 필요하다
오늘날의 TCP에서는 슬라이딩 윈도우(Sliding Window) 기법을 사용한다.
슬라이딩 윈도우(Sliding Window): TCP 흐름 제어 기법
윈도우(Window)란 송신 호스트가 파이프라이닝 할 수 있는 최대량을 의미한다. 즉, 윈도우의 크기만큼은 수신 호스트로부터 확인 응답을 받지 않고도 한 번에 전송할 수 있다는 의미이다. 만약, 수신 호스트로부터 첫 번째 세그먼트에 대한 ACK 세그먼트(확인 응답)을 받았다면, 윈도우는 오른쪽으로 한 칸 이동하게 될 것이다.
참고로, 수신 측의 윈도우 말고도 송신 측의 윈도우(송신 윈도우)도 있다. 수신 호스트가 처리할 수 있는 데이터를 동적으로 변경할 수 있으며, 이 정보를 송신 측에 TCP 헤더(윈도우 필드)를 통해 알려주고, 송신 측은 이렇게 전달받은 값을 통해 송신 윈도우를 계산한다. 따라서 송신 윈도우 크기는 가변적이며, 이는 수신 호스트의 상태에 따라 크게 영향을 받는다.
송신 윈도우와 수신 윈도우의 관계
TCP는 최소값(min)을 사용하여 송신 윈도우를 설정하는데, 실제 송신 윈도우 크기는 수신 윈도우와 혼잡 윈도우 중 작은 값에 의해 결정된다. 이는 혼잡 제어와 흐름 제어를 동시에 만족하기 위함이다.
이를 토대로 흐름 제어를 정리하면 다음 그림과 같다.
- 송신측이 세그먼트를 보낸다.
- 수신측은 세그먼트를 받고, 수신 윈도우를 한칸 이동시킨다. 이후 확인 응답을 송신측에 보낸다.
- 송신측은 확인 응답을 받고, 송신 윈도우를 한칸 이동시킨다.
- 1 ~ 3의 과정을 반복한다.
혼잡 제어(Congestion Control)
혼잡 제어를 이해하기 전에, '혼잡'이란 많은 트래픽으로 인해 패킷의 처리 속도가 늦어지거나 유실될 우러가 있는 네트워크 상황을 말한다. 즉, 트래픽이 너무 많이 몰리는 상황으로 이해하면 좋다. 혼잡 상황에서는 수많은 재전송 패킷들이 발생하게 되고 이로 인해 더 심한 혼잡 상황을 만들어 결국에는 네트워크가 붕괴되는 상황까지 갈 수 있다. => '혼잡 붕괴'
TCP의 혼잡 제어란, '송신 호스트'가 혼잡한 정도에 맞춰 유동적으로 전송량을 조절하는 기능을 말한다. 흐름 제어의 주체가 수신 호스트라면 혼잡 제어의 주체는 송신 호스트이다.
혼잡 제어에서도 '윈도우'라는 것이 사용된다.
- 혼잡 윈도우(Congestion Window): 혼잡 없이 전송할 수 있을 법한 데이터 양
- 혼잡 윈도우가 크면, 한번에 전송할 수 있는 세그먼트 수가 많음
- 혼잡 윈도우가 작으면, 네트워크가 혼잡한 상황이라는 의미이므로 한번에 전송할 수 있는 세그먼트 수가 적음
- 수신 윈도우는 수신 호스트가 헤더로 알려주었던 것과 반대로, 혼잡 윈도우는 송신 호스트가 알아서 직접 계산해서 알아내야 한다. (혼잡 제어의 주체는 송신 호스트이기 때문)
그렇다면 송신 호스트는 어떻게 혼잡 윈도우 값을 계산할 수 있을까?
-> '혼잡 제어 알고리즘'을 활용한다.
혼잡 제어 알고리즘이란 혼잡 제어를 수행하는 일련의 방법으로, 가장 기본적인 알고리즘으로 AIMD(Additive Increase/Multiplicative Decrease)
가 있다.
AIMD 알고리즘
- '합으로 증가, 곱으로 감소'
- 혼잡이 감지되지 않으면 -> 혼잡 윈도우를 RTT(Round Trip Time)마다 1씩 선형적으로 증가
- RTT는 메시지를 전송한 뒤 그에 대한 응답을 받는 데까지 걸리는 시간을 말한다.
- 최신 표준에서는 초기값을 1보다 더 큰 값(일반적으로 10 MSS)으로 권장한다. 초기값이 클수록 느린 시작 초기 단계에서 성능이 개선될 수 있다.
- 혼잡이 감지되면 -> 혼잡 윈도우를 절반으로 떨어뜨리는 동작을 반복
- 혼잡을 감지하는 방법은 오류 감지하는 방법과 동일하다.
- 중복된 ACK 세그먼트를 수신했을 때
- 타임아웃이 발생했을 때
- 혼잡을 감지하는 방법은 오류 감지하는 방법과 동일하다.
- AIMD를 사용하면 혼잡 윈도우는 톱니 모양으로 변화하게 된다
느린 시작(Slow Start)
- 혼잡 윈도우를 1부터 시작해서 문제없이 수신된 ACK 세그먼트 하나당 1씩 증가시키는 방식
- 혼잡 윈도우는 RTT마다 2배씩 지수적으로 증가하게 됨! -> 초기 전송 속도 빠른 확보
- 그렇다고 혼잡 윈도우를 무한정 늘릴 수 있는 것은 아니다. '느린 시작 임계치(slow start threshold)'라는 값까지만 증가시킬 수 있다.
- 혼잡 윈도우 값이 계속 증가하다가 다음의 상황 중 한 가지로 처리된다.
- '혼잡 윈도우 크기 >= 느린 시작 임계치' -> 느린 시작 종료, 혼잡 회피 수행
- 타임아웃 발생 -> 혼잡 윈도우 값을 1로, 느린 시작 임계치를 혼잡이 감지되었을 시점의 혼잡 윈도우 값의 절반으로 초기화한 뒤 다시 느린 시작 전개
- 세 번의 중복된 ACK 세그먼트를 수신 -> 빠른 재전송 후, 혼잡 윈도우를 절반으로 줄이고, 빠른 회복 수행
혼잡 회피(Congestion Avoidance)
- RTT마다 혼잡 윈도우를 1씩 증가시키는 알고리즘
- 느린 시작 알고리즘에서는 지수적으로 증가했지만, 혼잡 회피 알고리즘에서는 혼잡 윈도우 크기 선형적으로 증가
- 느린 시작 임계치를 넘어서면 혼잡 여지가 있으니 조심해서 혼잡 윈도우 증가하기 -> 조심해서 증가시키기
빠른 재전송 (Fast Retransmit) (= Triple-Duplicate-ACK)
빠른 재전송은 타임아웃이 발생했을 때의 재전송을 조금이라도 더 빨리하기 위한 기법으로, 오늘날의 TCP에서는 대부분이 기능이 활성화되어 있다. 빠른 재전송이란, 재전송 타이머의 타임 아웃 기간이 상대적으로 너무 길어 타이머가 만료되기 전이라도 세 번의 동일한 ACK 세그먼트를 받았다면 해당 세그먼트 이후의 세그먼트가 손실된 것으로 가정하고 곧바로 재전송하는 기능을 말한다. 즉, 수신측이 기다리는 순서 번호의 세그먼트보다 큰 순서번호의 세그먼트가 3개 도착할 경우를 의미한다. 이러한 특성 때문에 Triple-Duplicate-ACK
라고도 불린다. 이를 통해, 타이머가 끝날 때까지 기다리는 시간을 줄일 수 있다.
위 그림에서의 예시를 보자. Host A는 동일한 데이터에 대해 3개의 ACK를 수신하면 ACK된 데이터 이후의 세그먼트가 손실된 것으로 가정한다.
- Host A에서 보낸 2번째 패킷이 손실되어 Host B는 3, 4, 5번 패킷 수신 시 각각 Duplicate ACK를 Host A에게 보낸다. (총 3개의 Duplicate ACK 전송)
- Duplicate ACK는 비정상적인 순서(out-of-order)의 패킷이 수신될 시 수신측(Host B)에서 발생시킨다
- 즉, 현재까지 ACK가 완료된 패킷 다음 패킷이 손실난 상태에서 다음 패킷들이 계속 수신되는 경우 Duplicate ACK를 발생시킨다.
- 재전송 타이머가 종료되기 전까지 시간이 남앗지만, Host A는 2번째 패킷이 손실된 것으로 가정하고 즉시 재전송한다.
빠른 재전송은 보통 빠른 회복과 함께 발생한다.
TCP 구현마다 중복 ACK 기준 값(3 이상)이 다를 수 있다. 특히, 혼잡한 네트워크에서는 더 많은 중복 ACK를 요구하도록 설정하는 경우도 있다.
빠른 회복(Fast recovery)
세 번의 중복된 ACK 세그먼트를 수신한 상황은 타임아웃이 발생한 상황보다는 심각한 상황이 아니다. 때문에, 이 정도는 그렇게 큰 문제가 아니라고 생각하고 느린 시작 알고리즘의 재수행 없이 혼잡 회피를 수행하는 알고리즘이다.
빠른 회복(Fast Recovery) 알고리즘은 혼잡 윈도우를 1로 초기화하여 다시 시작하는 것이 아니라 '절반'으로 줄인 후, 빠른 전송률의 회복을 위해서 느린 시작을 건너뛰고 혼잡 회피를 수행하는 알고리즘이다. 단, 빠른 회복 도중이더라도 타임아웃이 발생하면 다시 느린 시작을 수행한다.
ECN: 명시적 혼잡 알림
ECN 역시 혼잡 제어 방법의 일환인데, 이전까지의 TCP 혼잡 제어는 오로지 본인의 힘으로 혼잡 제어를 수행했던 것과는 달리 ECN은 중간 노드(ex. 라우터)의 도움으로 혼잡을 제어한다. 오늘날의 네트워크환경에서 적극적으로 활용된다.
호스트가 ECN을 지원할 경우, 위와 같이 TCP/IP 헤더에 ECN 관련 비트가 추가된다.
ECN을 통한 혼잡 제어
- 호스트 A가 라우터에 패킷을 보낸다.
- 라우터가 혼잡을 감지한 경우, 패킷의 IP 헤더의 ECN 비트를 '11'로 수정하여 호스트 B에게 패킷을 전달한다.
- 호스트 B가 패킷을 확인했을 때, ECN 비트가 '11'인 경우, 응답 패킷을 보낼 때 TCP 세그먼트의 ECE 비트를 '1'로 설정하여 보낸다.
- 이 패킷을 수신한 호스트 A는 ECE 비트가 1이므로 혼잡 제어를 수행하면서 혼잡 윈도우를 조절하여 세그먼트를 조심히 호스트 B에게 전송한다. 이때, TCP 세그먼트의 CWR비트는 '1'로 설정한다.
송신 호스트만 혼잡 제어를 수행했을 경우, 문제가 발생한 이후에야 비로소 혼잡 제어가 가능했다는 문제점이 존재했지만, ECN을 사용하면 수신 호스트의 ACK 세그먼트를 통해서 더 빠르게 혼잡을 감지할 수 있다!
'Network' 카테고리의 다른 글
[Network] DNS Record (0) | 2024.11.26 |
---|---|
[Network] 그래서 게이트웨이(Gateway)가 뭔데 (0) | 2024.11.25 |
[Network] L4 스위치(LoadBalancer) 원리 (2) | 2024.11.22 |
[Network] 인터넷 공유기의 작동 원리 (0) | 2024.11.21 |
[Network] 네트워크의 3가지 구조(Inline, Out of Path, Proxy) (1) | 2024.11.20 |