Skip to content

Split View: [컴퓨터 네트워크] 10. TCP 완전 정복: 연결, 흐름제어, 혼잡제어

|

[컴퓨터 네트워크] 10. TCP 완전 정복: 연결, 흐름제어, 혼잡제어

본 포스팅은 James Kurose, Keith Ross의 Computer Networking: A Top-Down Approach (6th Edition) 교재를 기반으로 정리한 내용입니다.


1. TCP 연결

1.1 TCP 연결의 특징

TCP 연결의 핵심 속성:
  ├── 연결 지향 (Connection-Oriented)
  │   데이터 전송 전에 반드시 연결 수립
  ├── 전이중 (Full-Duplex)
  │   양방향 동시 데이터 전송
  ├── 점대점 (Point-to-Point)
  │   정확히 하나의 송신자와 하나의 수신자
  └── 바이트 스트림 서비스
      메시지 경계 없이 연속된 바이트 흐름

1.2 3-Way Handshake

TCP 연결 수립 과정이다.

클라이언트                        서버
   |                               |
   |── SYN (seq=client_isn) ──────>|  1단계: SYN
   |                               |
   |<── SYN+ACK ──────────────────|  2단계: SYN+ACK
   |   (seq=server_isn,            |
   |    ack=client_isn+1)          |
   |                               |
   |── ACK (ack=server_isn+1) ───>|  3단계: ACK
   |   (데이터 포함 가능)           |
   |                               |

각 단계 설명

1단계 - SYN:
  - 클라이언트가 SYN 세그먼트 전송
  - SYN 비트 = 1
  - 초기 순서 번호(client_isn) 설정
  - 데이터 없음

2단계 - SYN+ACK:
  - 서버가 SYN+ACK 세그먼트 응답
  - SYN 비트 = 1, ACK 비트 = 1
  - 서버의 초기 순서 번호(server_isn) 설정
  - 확인 번호 = client_isn + 1

3단계 - ACK:
  - 클라이언트가 ACK 세그먼트 전송
  - SYN 비트 = 0 (연결 수립 완료)
  - 이 세그먼트부터 데이터 포함 가능

1.3 TCP 연결 종료 (4-Way Handshake)

클라이언트                        서버
   |                               |
   |── FIN ───────────────────────>|  1단계
   |                               |
   |<── ACK ──────────────────────|  2단계
   |                               |
   |<── FIN ──────────────────────|  3단계
   |                               |
   |── ACK ───────────────────────>|  4단계
   |                               |
   | (TIME_WAIT: 30초 대기)        |
   |   → 연결 완전 종료             |

TIME_WAIT 상태: 마지막 ACK가 손실되었을 때 FIN 재전송에 대응하기 위해 일정 시간 대기한다.


2. TCP 세그먼트 구조

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
┌───────────────────────┬───────────────────────┐
│     출발지 포트 (16)    │     목적지 포트 (16)    │
├───────────────────────┴───────────────────────┤
│                순서 번호 (32)                    │
├───────────────────────────────────────────────┤
│                확인 번호 (32)                    │
├────────┬──────┬───────┬───────────────────────┤
│헤더길이 │미사용│플래그  │    수신 윈도우 (16)      │
│  (4)   │ (6)  │(6bits)│                        │
├────────┴──────┴───────┼───────────────────────┤
│     체크섬 (16)        │   긴급 포인터 (16)      │
├───────────────────────┴───────────────────────┤
│              옵션 (가변 길이)                     │
├───────────────────────────────────────────────┤
│                                                │
│              데이터 (가변 길이)                    │
│                                                │
└───────────────────────────────────────────────┘

주요 필드

필드크기설명
순서 번호32 bits세그먼트 데이터의 첫 바이트 번호
확인 번호32 bits기대하는 다음 바이트 번호
수신 윈도우16 bits수신 가능한 바이트 수 (흐름 제어)
헤더 길이4 bitsTCP 헤더 길이 (4바이트 단위)
플래그 비트6 bitsSYN, ACK, FIN, RST, PSH, URG

3. 순서 번호와 확인 번호

3.1 순서 번호 (Sequence Number)

세그먼트에 포함된 데이터의 첫 번째 바이트의 바이트 스트림 번호다.

예시: 500,000 바이트 파일, MSS = 1,000 바이트

세그먼트 1: seq = 0,     데이터 = 바이트 0~999
세그먼트 2: seq = 1000,  데이터 = 바이트 1000~1999
세그먼트 3: seq = 2000,  데이터 = 바이트 2000~2999
...
세그먼트 500: seq = 499000, 데이터 = 바이트 499000~499999

3.2 확인 번호 (Acknowledgment Number)

수신자가 다음으로 기대하는 바이트 번호다. 누적 확인(cumulative acknowledgment) 방식이다.

예시: 텔넷 세션에서 'C'를 입력

호스트 A                          호스트 B
   |── seq=42, ack=79, 'C' ───>|
   |                             |  'C' 수신, 에코 응답
   |<── seq=79, ack=43, 'C' ───|
   |                             |
   |── seq=43, ack=80 ──────── >|  (ACK)

  seq=42: A가 보내는 데이터의 42번째 바이트
  ack=79: A가 B로부터 79번째 바이트를 기대
  ack=43: B가 A로부터 43번째 바이트를 기대 (42번 수신 완료)

4. RTT 추정과 타임아웃

4.1 SampleRTT

실제 측정한 RTT 값이다. 세그먼트 전송 시점부터 ACK 수신 시점까지의 시간이다.

  • 재전송된 세그먼트는 측정에서 제외
  • SampleRTT는 변동이 크다

4.2 EstimatedRTT (지수 가중 이동 평균)

EstimatedRTT = (1 - alpha) * EstimatedRTT + alpha * SampleRTT

  alpha = 0.125 (권장값)

  → 최근 측정값에 더 큰 가중치
  → SampleRTT의 급격한 변동을 완화

4.3 DevRTT (RTT 편차)

DevRTT = (1 - beta) * DevRTT + beta * |SampleRTT - EstimatedRTT|

  beta = 0.25 (권장값)

4.4 타임아웃 간격

TimeoutInterval = EstimatedRTT + 4 * DevRTT

  EstimatedRTT: 평균 RTT 추정
  4 * DevRTT: 안전 마진 (변동성 고려)
RTT 추정 예시 (시간 경과에 따른 변화):

RTT
(ms)
 ^
 │  *    *
 │   *  * *  *         SampleRTT (변동 큼)
 │    **    * *  *
 │  ___________*____   EstimatedRTT (안정적)
 │                     TimeoutInterval (상한선)
 └──────────────────> 시간

5. TCP 신뢰적 데이터 전송

TCP는 IP의 비신뢰적 서비스 위에 신뢰적 전송을 구현한다.

5.1 TCP 송신자의 핵심 이벤트

이벤트 1: 상위 계층으로부터 데이터 수신
  → 세그먼트 생성, 순서 번호 부여
  → IP에 전달
  → 타이머가 실행 중이 아니면 시작

이벤트 2: 타이머 만료
  → 가장 오래된 미확인 세그먼트 재전송
  → 타이머 재시작

이벤트 3: ACK 수신
  → SendBase 업데이트 (누적 확인)
  → 아직 미확인 세그먼트가 있으면 타이머 재시작

5.2 TCP 재전송 시나리오

시나리오 1: ACK 손실

호스트 A                    호스트 B
  |── seq=92, 8바이트 ───>|
  |                        |── ACK=100 (손실!)
  | 타이머 만료             |
  |── seq=92, 8바이트 ───>|  (재전송)
  |<── ACK=100 ───────── |

시나리오 2: 조기 타임아웃

호스트 A                    호스트 B
  |── seq=92, 8바이트 ───>|
  |── seq=100, 20바이트 ─>|
  |                        |── ACK=100
  | 타이머 만료!            |── ACK=120
  | (ACK=100이 아직 도착 안 함)
  |── seq=92, 8바이트 ───>|  (불필요한 재전송)
  |<── ACK=100 ───────── |
  |<── ACK=120 ───────── |  (누적 ACK로 자연 해결)

시나리오 3: 누적 ACK

호스트 A                    호스트 B
  |── seq=92, 8바이트 ───>|
  |── seq=100, 20바이트 ─>|
  |                        |── ACK=100 (손실!)
  |                        |── ACK=120 (도착)
  |<── ACK=120 ───────── |

  ACK=120은 120 이전의 모든 바이트 확인
  → seq=92 패킷도 확인된 것!
  → 재전송 불필요

5.3 빠른 재전송 (Fast Retransmit)

타임아웃을 기다리지 않고, 3개의 중복 ACK를 받으면 즉시 재전송한다.

호스트 A                    호스트 B
  |── seq=92 ────────────>|  ACK=100
  |── seq=100 ───────────>|  (손실!)
  |── seq=120 ───────────>|  ACK=100 (중복 1)
  |── seq=140 ───────────>|  ACK=100 (중복 2)
  |── seq=160 ───────────>|  ACK=100 (중복 3)
  |                        |
  | 3개 중복 ACK 수신!       |
  | 타이머 만료 전에 즉시 재전송
  |── seq=100 ───────────>|  ACK=180 (누적 확인)

3개의 중복 ACK = 원래 ACK + 추가 3개 = 총 4번의 동일한 ACK


6. 흐름 제어 (Flow Control)

6.1 문제

송신자가 너무 빠르게 데이터를 보내면 수신자의 버퍼가 넘칠 수 있다.

수신 측 버퍼:
  ┌──────────────────────────────┐
  │[데이터][데이터][  빈 공간     ]│
  └──────────────────────────────┘
  │←── 사용 중 ──→│←── rwnd ────→│
                    수신 윈도우

6.2 수신 윈도우 (Receive Window)

TCP는 수신 윈도우(rwnd) 를 통해 흐름 제어를 수행한다.

rwnd = RcvBuffer - (LastByteRcvd - LastByteRead)

  RcvBuffer: 수신 버퍼의 전체 크기
  LastByteRcvd: 마지막으로 수신된 바이트 번호
  LastByteRead: 상위 계층이 읽어간 마지막 바이트 번호

6.3 동작 방식

수신자: ACK에 rwnd 값을 포함하여 전송

  ACK 세그먼트:
  ┌────────┬────────┐
  │ ACK=N  │ rwnd=X │  "N번째 바이트까지 받았고,
  └────────┴────────┘   X 바이트만큼 더 받을 수 있어"

송신자: rwnd를 초과하지 않도록 전송량 제한

  LastByteSent - LastByteAcked <= rwnd

  rwnd가 줄어들면 → 전송 속도 감소
  rwnd가 0이면 → 전송 중단 (단, 1바이트 프로브 패킷 전송)

rwnd = 0 일 때의 문제

문제: 수신자가 rwnd=0을 보낸 후 버퍼를 비워도,
     송신자에게 알릴 방법이 없음 (보낼 데이터가 없으므로)

해결: 송신자가 주기적으로 1바이트 프로브(probe) 세그먼트 전송
  → 수신자가 현재 rwnd 값을 포함한 ACK로 응답
  → 빈 공간이 생기면 송신 재개

7. TCP 혼잡 제어 (Congestion Control)

7.1 혼잡이란

혼잡(Congestion):
  네트워크 내 데이터 양이 네트워크 용량을 초과하는 상태

증상:
  ├── 패킷 손실 (라우터 버퍼 오버플로)
  ├── 긴 지연 (라우터 큐에서 대기)
  └── 불필요한 재전송 (타임아웃으로 인한)

7.2 혼잡 제어 vs 흐름 제어

흐름 제어:  수신자 보호 (수신 버퍼 오버플로 방지)
            → rwnd로 제어

혼잡 제어:  네트워크 보호 (네트워크 과부하 방지)
            → cwnd(congestion window)로 제어

실제 전송량:
  LastByteSent - LastByteAcked <= min(cwnd, rwnd)

7.3 AIMD (Additive Increase Multiplicative Decrease)

TCP 혼잡 제어의 기본 철학이다.

cwnd 조정 원칙:

  패킷 손실 없음 (ACK 정상 수신):
    → cwnd 증가 (대역폭 탐색)

  패킷 손실 발생 (타임아웃 또는 3중복 ACK):
    → cwnd 감소 (혼잡 완화)

  "톱니 형태" 패턴:

  cwnd
    ^
    │    /\      /\      /\
    │   /  \    /  \    /  \
    │  /    \  /    \  /    \
    │ /      \/      \/      \
    └──────────────────────────> 시간

7.4 슬로 스타트 (Slow Start)

연결 초기에 cwnd를 지수적으로 증가시킨다.

초기 cwnd = 1 MSS

각 ACK 수신 시: cwnd += 1 MSS
(한 RTT에 모든 ACK를 받으면 cwnd가 2배)

cwnd 변화:
  RTT 1: cwnd = 1 MSS  → 1개 세그먼트 전송
  RTT 2: cwnd = 2 MSS  → 2개 세그먼트 전송
  RTT 3: cwnd = 4 MSS  → 4개 세그먼트 전송
  RTT 4: cwnd = 8 MSS  → 8개 세그먼트 전송
  ...

  지수적 증가: 1, 2, 4, 8, 16, 32, ...

슬로 스타트의 종료 조건

1. cwnd >= ssthresh (느린 시작 임계값) → 혼잡 회피로 전환
2. 타임아웃 발생 → ssthresh = cwnd/2, cwnd = 1 MSS, 슬로 스타트 재시작
3. 3개 중복 ACK → ssthresh = cwnd/2, cwnd = ssthresh + 3, 빠른 회복

7.5 혼잡 회피 (Congestion Avoidance)

cwnd가 ssthresh에 도달한 후 선형적으로 증가시킨다.

각 RTT마다: cwnd += 1 MSS
(ACK 하나당: cwnd += MSS * MSS / cwnd)

cwnd 변화 (MSS 단위):
  RTT n:   cwnd = 10
  RTT n+1: cwnd = 11
  RTT n+2: cwnd = 12
  ...

  선형 증가: 10, 11, 12, 13, ...

혼잡 이벤트 시 동작

타임아웃 발생:
  ssthresh = cwnd / 2
  cwnd = 1 MSS
  → 슬로 스타트로 복귀

3개 중복 ACK:
  ssthresh = cwnd / 2
  cwnd = ssthresh + 3 MSS
  → 빠른 회복으로 전환

7.6 빠른 회복 (Fast Recovery)

3개의 중복 ACK를 받았을 때의 상태다. TCP Reno에서 도입되었다.

빠른 회복 동작:
  1. 중복 ACK 수신할 때마다: cwnd += 1 MSS
  2. 새 ACK 수신 (손실 복구 완료):
     cwnd = ssthresh
     → 혼잡 회피로 전환
  3. 타임아웃 발생:
     ssthresh = cwnd / 2
     cwnd = 1 MSS
     → 슬로 스타트로 복귀

7.7 TCP 혼잡 제어 전체 상태 다이어그램

                    ┌─────────────┐
       시작 ───────>│  슬로 스타트  │
                    │ cwnd 지수 증가│
                    └──────┬──────┘
                cwnd >= ssthresh
                    ┌──────▼──────┐
              ┌────>│  혼잡 회피   │<────┐
              │     │ cwnd 선형 증가│     │
              │     └──────┬──────┘     │
              │            │            │
         새 ACK      3중복 ACK     타임아웃
         (복구완료)        │            │
              │     ┌──────▼──────┐     │
              │     │  빠른 회복   │     │
              └─────│ cwnd 조정    │     │
                    └─────────────┘     │
                           │            │
                      타임아웃           │
                           └────────────┘
                           ssthresh=cwnd/2
                           cwnd=1 MSS
                           → 슬로 스타트

7.8 TCP Tahoe vs TCP Reno

cwnd
  ^
  │           *
  │          * *
  │         *   *        TCP Reno
  │        *     *      /
  │       *       *    *
  │      *         *  * *
  │     *           **   *
  │    *                  *
  │   *
  │  * TCP Tahoe: 항상 cwnd=1로 복귀
  │ *
  └─────────────────────────────> 시간
       ↑         ↑
     손실1     손실2
이벤트TCP TahoeTCP Reno
타임아웃cwnd = 1 MSScwnd = 1 MSS
3중복 ACKcwnd = 1 MSScwnd = cwnd/2 (빠른 회복)

8. TCP 공정성 (Fairness)

8.1 공정성의 정의

용량 R인 병목 링크를 K개의 TCP 연결이 공유할 때, 각 연결이 R/K의 처리량을 얻는 것이 이상적이다.

8.2 TCP가 공정한 이유

두 연결이 대역폭 R을 공유하는 경우:

처리량2
    ^
    │  ╲  공정 지점
    │   ╲ (R/2, R/2)
    │    ╲   *
R   │     ╲ / \
    │      *   *
    │     / ╲   \
    │    /   *   *
    │   /   / ╲   \
    │  /   /   *   *  → 공정 지점으로 수렴
    └──────────────────> 처리량1
    0                 R

  AIMD가 공정 지점으로 수렴하는 과정:
  1. 두 연결이 균등하게 cwnd 증가 (Additive Increase)
     → 45도 방향으로 이동 (총합 = R 선을 향해)
  2. 손실 발생 시 각각 cwnd를 절반으로 (Multiplicative Decrease)
     → 원점 방향으로 이동
  3. 반복하면 공정 지점(R/2, R/2)으로 수렴

8.3 공정성의 현실적 한계

UDP는 혼잡 제어를 하지 않음:
  → TCP가 양보한 대역폭을 UDP가 차지
  → TCP에 불공정

병렬 TCP 연결:
  → 하나의 애플리케이션이 여러 TCP 연결을 열면
  → 단일 연결 애플리케이션보다 더 많은 대역폭 차지
  → 예: 브라우저가 동시에 여러 연결로 웹 객체 다운로드

9. 정리

TCP 핵심 메커니즘 요약:

  연결 관리:
  ├── 3-way handshake (SYN → SYN+ACK → ACK)
  └── 4-way handshake 종료 (FIN → ACK → FIN → ACK)

  신뢰적 전송:
  ├── 순서 번호 + 확인 번호 (누적 ACK)
  ├── 타이머 기반 재전송
  ├── 빠른 재전송 (3중복 ACK)
  └── RTT 추정 (EWMA)

  흐름 제어:
  └── rwnd (수신 윈도우)로 수신자 보호

  혼잡 제어:
  ├── 슬로 스타트: 지수적 증가
  ├── 혼잡 회피: 선형적 증가
  ├── 빠른 회복: 3중복 ACK 시 cwnd 절반
  └── AIMD → 공정한 대역폭 공유

10. 확인 문제

Q1. 3-way handshake에서 왜 3번의 메시지 교환이 필요한가?

1번 (SYN): 클라이언트가 연결을 요청하고 자신의 초기 순서 번호를 알린다. 2번 (SYN+ACK): 서버가 연결을 수락하고 자신의 초기 순서 번호를 알리며, 클라이언트의 순서 번호를 확인한다. 3번 (ACK): 클라이언트가 서버의 순서 번호를 확인한다.

이 과정을 통해 양측 모두 상대방의 초기 순서 번호를 확인하고, 연결 의사를 확인한다. 2번만으로는 서버가 보낸 SYN+ACK를 클라이언트가 수신했는지 서버가 알 수 없다.

Q2. 흐름 제어와 혼잡 제어의 차이점은?
  • 흐름 제어: 수신자를 보호한다. 수신 버퍼가 넘치지 않도록 rwnd(수신 윈도우)를 사용하여 송신자의 전송량을 제한한다.
  • 혼잡 제어: 네트워크를 보호한다. 네트워크가 과부하되지 않도록 cwnd(혼잡 윈도우)를 사용하여 송신자의 전송량을 제한한다.

실제 전송량은 min(cwnd, rwnd)에 의해 결정된다.

Q3. 슬로 스타트에서 cwnd가 지수적으로 증가하는데 왜 "느린(slow)" 시작인가?

"느린 시작"이라는 이름은 초기 cwnd1 MSS로 매우 작게 시작한다는 데서 유래한다. TCP 이전의 프로토콜들은 연결 시작 시 허용된 최대 윈도우 크기로 바로 데이터를 쏟아부었는데, 이는 네트워크 혼잡을 유발했다. 슬로 스타트는 이에 비해 "느리게" 1 MSS부터 시작한다는 의미다. 물론 지수적 증가이므로 실제로는 빠르게 증가한다.

Q4. TCP Reno에서 타임아웃과 3중복 ACK를 다르게 처리하는 이유는?

3중복 ACK는 특정 세그먼트만 손실되었지만 그 이후의 세그먼트는 도착했다는 의미다. 네트워크가 여전히 일부 패킷을 전달하고 있으므로 혼잡이 심각하지 않다고 판단하여 cwnd를 절반으로만 줄인다 (빠른 회복).

반면 타임아웃은 아무 ACK도 오지 않는 상황으로, 네트워크 혼잡이 심각하다고 판단하여 cwnd를 1 MSS로 초기화하고 슬로 스타트부터 다시 시작한다.

[Computer Networking] 10. TCP Deep Dive: Connection, Flow Control, Congestion Control

This post is based on the textbook Computer Networking: A Top-Down Approach (6th Edition) by James Kurose and Keith Ross.


1. TCP Connection

1.1 Characteristics of a TCP Connection

Key properties of a TCP connection:
  +-- Connection-Oriented
  |   Connection must be established before data transfer
  +-- Full-Duplex
  |   Simultaneous bidirectional data transfer
  +-- Point-to-Point
  |   Exactly one sender and one receiver
  +-- Byte Stream Service
      Continuous byte flow without message boundaries

1.2 3-Way Handshake

The TCP connection establishment process.

Client                        Server
   |                               |
   |-- SYN (seq=client_isn) ------>|  Step 1: SYN
   |                               |
   |<-- SYN+ACK ------------------|  Step 2: SYN+ACK
   |   (seq=server_isn,            |
   |    ack=client_isn+1)          |
   |                               |
   |-- ACK (ack=server_isn+1) --->|  Step 3: ACK
   |   (may include data)          |
   |                               |

Step-by-Step Explanation

Step 1 - SYN:
  - Client sends a SYN segment
  - SYN bit = 1
  - Sets initial sequence number (client_isn)
  - No data

Step 2 - SYN+ACK:
  - Server responds with SYN+ACK segment
  - SYN bit = 1, ACK bit = 1
  - Sets server's initial sequence number (server_isn)
  - Acknowledgment number = client_isn + 1

Step 3 - ACK:
  - Client sends ACK segment
  - SYN bit = 0 (connection established)
  - Data can be included from this segment onward

1.3 TCP Connection Termination (4-Way Handshake)

Client                        Server
   |                               |
   |-- FIN ----------------------->|  Step 1
   |                               |
   |<-- ACK -----------------------|  Step 2
   |                               |
   |<-- FIN -----------------------|  Step 3
   |                               |
   |-- ACK ----------------------->|  Step 4
   |                               |
   | (TIME_WAIT: 30 sec wait)      |
   |   -> Connection fully closed   |

TIME_WAIT state: The client waits for a period to handle potential FIN retransmissions in case the last ACK is lost.


2. TCP Segment Structure

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-----------------------+-----------------------+
|   Source port (16)    |   Dest port (16)      |
+-----------------------+-----------------------+
|            Sequence number (32)               |
+-----------------------------------------------+
|         Acknowledgment number (32)            |
+--------+------+-------+-----------------------+
| Header | Unused|Flags  |   Receive window (16) |
| len(4) | (6)   |(6bits)|                       |
+--------+------+-------+-----------------------+
|    Checksum (16)      | Urgent pointer (16)   |
+-----------------------+-----------------------+
|           Options (variable length)           |
+-----------------------------------------------+
|                                               |
|           Data (variable length)              |
|                                               |
+-----------------------------------------------+

Key Fields

FieldSizeDescription
Sequence number32 bitsByte number of first data byte in segment
ACK number32 bitsNext byte number expected
Receive window16 bitsReceivable byte count (flow control)
Header length4 bitsTCP header length (in 4-byte units)
Flag bits6 bitsSYN, ACK, FIN, RST, PSH, URG

3. Sequence Numbers and Acknowledgment Numbers

3.1 Sequence Number

The byte stream number of the first byte of data in the segment.

Example: 500,000 byte file, MSS = 1,000 bytes

Segment 1: seq = 0,      data = bytes 0-999
Segment 2: seq = 1000,   data = bytes 1000-1999
Segment 3: seq = 2000,   data = bytes 2000-2999
...
Segment 500: seq = 499000, data = bytes 499000-499999

3.2 Acknowledgment Number

The next byte number the receiver expects. Uses cumulative acknowledgment.

Example: Typing 'C' in a telnet session

Host A                          Host B
   |-- seq=42, ack=79, 'C' --->|
   |                             |  Receives 'C', echo response
   |<-- seq=79, ack=43, 'C' ---|
   |                             |
   |-- seq=43, ack=80 -------->|  (ACK)

  seq=42: 42nd byte that A is sending
  ack=79: A expects byte 79 from B
  ack=43: B expects byte 43 from A (byte 42 received)

4. RTT Estimation and Timeout

4.1 SampleRTT

The actually measured RTT value. The time from segment transmission to ACK reception.

  • Retransmitted segments are excluded from measurement
  • SampleRTT is highly variable

4.2 EstimatedRTT (Exponential Weighted Moving Average)

EstimatedRTT = (1 - alpha) * EstimatedRTT + alpha * SampleRTT

  alpha = 0.125 (recommended value)

  -> More weight on recent measurements
  -> Smooths out rapid fluctuations in SampleRTT

4.3 DevRTT (RTT Deviation)

DevRTT = (1 - beta) * DevRTT + beta * |SampleRTT - EstimatedRTT|

  beta = 0.25 (recommended value)

4.4 Timeout Interval

TimeoutInterval = EstimatedRTT + 4 * DevRTT

  EstimatedRTT: Average RTT estimate
  4 * DevRTT: Safety margin (accounting for variability)
RTT estimation example (changes over time):

RTT
(ms)
 ^
 |  *    *
 |   *  * *  *         SampleRTT (highly variable)
 |    **    * *  *
 |  ___________*____   EstimatedRTT (stable)
 |                     TimeoutInterval (upper bound)
 +---------------------> Time

5. TCP Reliable Data Transfer

TCP implements reliable transfer on top of IP's unreliable service.

5.1 Key Events for the TCP Sender

Event 1: Data received from upper layer
  -> Create segment, assign sequence number
  -> Pass to IP
  -> Start timer if not already running

Event 2: Timer expires
  -> Retransmit the oldest unacknowledged segment
  -> Restart timer

Event 3: ACK received
  -> Update SendBase (cumulative acknowledgment)
  -> Restart timer if there are still unacknowledged segments

5.2 TCP Retransmission Scenarios

Scenario 1: ACK Loss

Host A                    Host B
  |-- seq=92, 8 bytes --->|
  |                        |-- ACK=100 (lost!)
  | Timer expires          |
  |-- seq=92, 8 bytes --->|  (retransmit)
  |<-- ACK=100 ---------- |

Scenario 2: Premature Timeout

Host A                    Host B
  |-- seq=92, 8 bytes --->|
  |-- seq=100, 20 bytes ->|
  |                        |-- ACK=100
  | Timer expires!         |-- ACK=120
  | (ACK=100 not yet arrived)
  |-- seq=92, 8 bytes --->|  (unnecessary retransmit)
  |<-- ACK=100 ---------- |
  |<-- ACK=120 ---------- |  (cumulative ACK resolves naturally)

Scenario 3: Cumulative ACK

Host A                    Host B
  |-- seq=92, 8 bytes --->|
  |-- seq=100, 20 bytes ->|
  |                        |-- ACK=100 (lost!)
  |                        |-- ACK=120 (arrives)
  |<-- ACK=120 ---------- |

  ACK=120 confirms all bytes before 120
  -> seq=92 packet is also confirmed!
  -> No retransmission needed

5.3 Fast Retransmit

Instead of waiting for a timeout, retransmit immediately upon receiving 3 duplicate ACKs.

Host A                    Host B
  |-- seq=92 ------------>|  ACK=100
  |-- seq=100 ----------->|  (lost!)
  |-- seq=120 ----------->|  ACK=100 (dup 1)
  |-- seq=140 ----------->|  ACK=100 (dup 2)
  |-- seq=160 ----------->|  ACK=100 (dup 3)
  |                        |
  | 3 duplicate ACKs received!
  | Retransmit immediately before timer expires
  |-- seq=100 ----------->|  ACK=180 (cumulative)

3 duplicate ACKs = the original ACK + 3 additional = 4 total identical ACKs


6. Flow Control

6.1 The Problem

If the sender sends data too quickly, the receiver's buffer can overflow.

Receiver buffer:
  +------------------------------+
  |[Data][Data][  Free space     ]|
  +------------------------------+
  |<-- In use -->|<--- rwnd ---->|
                   Receive window

6.2 Receive Window (rwnd)

TCP uses the receive window (rwnd) for flow control.

rwnd = RcvBuffer - (LastByteRcvd - LastByteRead)

  RcvBuffer: Total size of the receive buffer
  LastByteRcvd: Last byte number received
  LastByteRead: Last byte number read by the upper layer

6.3 How It Works

Receiver: Includes rwnd value in ACK segments

  ACK segment:
  +--------+--------+
  | ACK=N  | rwnd=X |  "Received up to byte N,
  +--------+--------+   can accept X more bytes"

Sender: Limits transmission so as not to exceed rwnd

  LastByteSent - LastByteAcked <= rwnd

  As rwnd decreases -> transmission rate decreases
  When rwnd = 0 -> stop transmission (but send 1-byte probe packets)

The Problem When rwnd = 0

Problem: After receiver sends rwnd=0, even if it clears its buffer,
         there is no way to notify the sender (no data to send)

Solution: Sender periodically sends 1-byte probe segments
  -> Receiver responds with ACK containing current rwnd value
  -> When free space appears, transmission resumes

7. TCP Congestion Control

7.1 What Is Congestion

Congestion:
  A state where data volume in the network exceeds network capacity

Symptoms:
  +-- Packet loss (router buffer overflow)
  +-- Long delays (waiting in router queues)
  +-- Unnecessary retransmissions (due to timeouts)

7.2 Congestion Control vs Flow Control

Flow control:   Protects the receiver (prevents receive buffer overflow)
                -> Controlled by rwnd

Congestion control: Protects the network (prevents network overload)
                    -> Controlled by cwnd (congestion window)

Actual transmission rate:
  LastByteSent - LastByteAcked <= min(cwnd, rwnd)

7.3 AIMD (Additive Increase Multiplicative Decrease)

The fundamental philosophy of TCP congestion control.

cwnd adjustment principle:

  No packet loss (ACKs received normally):
    -> Increase cwnd (probing for bandwidth)

  Packet loss (timeout or 3 duplicate ACKs):
    -> Decrease cwnd (alleviating congestion)

  "Sawtooth" pattern:

  cwnd
    ^
    |    /\      /\      /\
    |   /  \    /  \    /  \
    |  /    \  /    \  /    \
    | /      \/      \/      \
    +---------------------------> Time

7.4 Slow Start

At the beginning of a connection, cwnd is increased exponentially.

Initial cwnd = 1 MSS

On each ACK received: cwnd += 1 MSS
(If all ACKs are received in one RTT, cwnd doubles)

cwnd progression:
  RTT 1: cwnd = 1 MSS  -> 1 segment sent
  RTT 2: cwnd = 2 MSS  -> 2 segments sent
  RTT 3: cwnd = 4 MSS  -> 4 segments sent
  RTT 4: cwnd = 8 MSS  -> 8 segments sent
  ...

  Exponential growth: 1, 2, 4, 8, 16, 32, ...

Slow Start Termination Conditions

1. cwnd >= ssthresh (slow start threshold) -> Switch to congestion avoidance
2. Timeout -> ssthresh = cwnd/2, cwnd = 1 MSS, restart slow start
3. 3 duplicate ACKs -> ssthresh = cwnd/2, cwnd = ssthresh + 3, fast recovery

7.5 Congestion Avoidance

After cwnd reaches ssthresh, increase linearly.

Each RTT: cwnd += 1 MSS
(Per ACK: cwnd += MSS * MSS / cwnd)

cwnd progression (in MSS units):
  RTT n:   cwnd = 10
  RTT n+1: cwnd = 11
  RTT n+2: cwnd = 12
  ...

  Linear increase: 10, 11, 12, 13, ...

Behavior on Congestion Events

Timeout:
  ssthresh = cwnd / 2
  cwnd = 1 MSS
  -> Return to slow start

3 duplicate ACKs:
  ssthresh = cwnd / 2
  cwnd = ssthresh + 3 MSS
  -> Enter fast recovery

7.6 Fast Recovery

The state entered upon receiving 3 duplicate ACKs. Introduced in TCP Reno.

Fast recovery operation:
  1. On each duplicate ACK received: cwnd += 1 MSS
  2. On new ACK received (loss recovery complete):
     cwnd = ssthresh
     -> Switch to congestion avoidance
  3. On timeout:
     ssthresh = cwnd / 2
     cwnd = 1 MSS
     -> Return to slow start

7.7 TCP Congestion Control State Diagram

                    +---------------+
       Start ------>| Slow Start    |
                    | cwnd exp.     |
                    | increase      |
                    +------+--------+
                           |
                cwnd >= ssthresh
                           |
                    +------v--------+
              +---->| Congestion    |<----+
              |     | Avoidance     |     |
              |     | cwnd linear   |     |
              |     | increase      |     |
              |     +------+--------+     |
              |            |              |
         New ACK      3 dup ACKs     Timeout
         (recovery        |              |
          complete)       |              |
              |     +------v--------+     |
              |     | Fast Recovery |     |
              +-----| cwnd adjust   |     |
                    +---------------+     |
                           |              |
                      Timeout             |
                           +--------------+
                           ssthresh=cwnd/2
                           cwnd=1 MSS
                           -> Slow Start

7.8 TCP Tahoe vs TCP Reno

cwnd
  ^
  |           *
  |          * *
  |         *   *        TCP Reno
  |        *     *      /
  |       *       *    *
  |      *         *  * *
  |     *           **   *
  |    *                  *
  |   *
  |  * TCP Tahoe: Always resets cwnd to 1
  | *
  +-------------------------------> Time
       ^         ^
     Loss 1    Loss 2
EventTCP TahoeTCP Reno
Timeoutcwnd = 1 MSScwnd = 1 MSS
3 dup ACKscwnd = 1 MSScwnd = cwnd/2 (fast recovery)

8. TCP Fairness

8.1 Definition of Fairness

When K TCP connections share a bottleneck link of capacity R, ideally each connection should get R/K throughput.

8.2 Why TCP Is Fair

Two connections sharing bandwidth R:

Throughput2
    ^
    |  \  Fair point
    |   \ (R/2, R/2)
    |    \   *
R   |     \ / \
    |      *   *
    |     / \   \
    |    /   *   *
    |   /   / \   \
    |  /   /   *   *  -> Converges to fair point
    +--------------------> Throughput1
    0                 R

  AIMD convergence process:
  1. Both connections increase cwnd equally (Additive Increase)
     -> Move at 45 degrees (toward the total=R line)
  2. On loss, each halves cwnd (Multiplicative Decrease)
     -> Move toward origin
  3. Repeating converges to the fair point (R/2, R/2)

8.3 Practical Limitations of Fairness

UDP does not perform congestion control:
  -> UDP takes bandwidth that TCP yields
  -> Unfair to TCP

Parallel TCP connections:
  -> An application with multiple TCP connections
  -> Gets more bandwidth than single-connection applications
  -> Example: Browsers downloading web objects over multiple connections

9. Summary

TCP key mechanisms summary:

  Connection management:
  +-- 3-way handshake (SYN -> SYN+ACK -> ACK)
  +-- 4-way handshake termination (FIN -> ACK -> FIN -> ACK)

  Reliable transfer:
  +-- Sequence numbers + acknowledgment numbers (cumulative ACK)
  +-- Timer-based retransmission
  +-- Fast retransmit (3 duplicate ACKs)
  +-- RTT estimation (EWMA)

  Flow control:
  +-- rwnd (receive window) protects the receiver

  Congestion control:
  +-- Slow start: Exponential increase
  +-- Congestion avoidance: Linear increase
  +-- Fast recovery: Halve cwnd on 3 dup ACKs
  +-- AIMD -> Fair bandwidth sharing

10. Review Questions

Q1. Why are 3 message exchanges needed in the 3-way handshake?

Step 1 (SYN): The client requests a connection and communicates its initial sequence number. Step 2 (SYN+ACK): The server accepts the connection, communicates its initial sequence number, and acknowledges the client's sequence number. Step 3 (ACK): The client acknowledges the server's sequence number.

Through this process, both sides confirm each other's initial sequence numbers and intent to connect. With only 2 steps, the server would not know whether the client received the SYN+ACK.

Q2. What is the difference between flow control and congestion control?
  • Flow control: Protects the receiver. Uses rwnd (receive window) to limit the sender's transmission rate so the receive buffer does not overflow.
  • Congestion control: Protects the network. Uses cwnd (congestion window) to limit the sender's transmission rate so the network does not become overloaded.

The actual transmission rate is determined by min(cwnd, rwnd).

Q3. In slow start, cwnd increases exponentially -- so why is it called "slow" start?

The name comes from the fact that the initial cwnd starts very small at 1 MSS. Protocols before TCP would immediately send data at the maximum allowed window size at the start of a connection, which caused network congestion. Slow start is "slow" in comparison because it starts from 1 MSS. Of course, since the growth is exponential, it actually increases rapidly.

Q4. Why does TCP Reno treat timeouts and 3 duplicate ACKs differently?

Three duplicate ACKs indicate that only a specific segment was lost, but segments after it are arriving. Since the network is still delivering some packets, the congestion is judged to be not severe, so cwnd is only halved (fast recovery).

In contrast, a timeout means no ACK is arriving at all, suggesting severe network congestion. Therefore, cwnd is reset to 1 MSS and slow start begins again from scratch.