1. Transport Layer 서비스
Transport layer는 서로 다른 호스트에서 실행 중인 application process 간에 논리적 통신(logical communication)을 제공한다.

- Sender: Application layer의 message를 받아 segment로 분할하고, 각 segment에 transport header를 추가한 후 network layer에 전달
- Receiver: Network layer에서 받은 segment를 재조립하여 application layer에 message를 전달
1.1 Transport Layer vs Network Layer
두 계층의 역할을 비유로 이해하면:
- Network layer: 호스트 간의 논리적 통신 (집과 집 사이의 우편 배달)
- Transport layer: Process 간의 논리적 통신 (집 안의 개인에게 편지를 전달하는 것)
Transport layer는 network layer가 제공하는 서비스 위에서 동작하므로, network layer의 한계(지연, 손실 등)를 근본적으로 해결할 수는 없다. 하지만 network layer가 보장하지 않는 것(예: 데이터 무결성)을 transport layer에서 추가로 제공할 수 있다.
1.2 Internet의 Transport Layer Protocol
| Protocol | 특성 |
|---|---|
| TCP | Reliable, in-order delivery. Congestion control, flow control, connection setup 제공 |
| UDP | Unreliable, unordered delivery. Best-effort IP의 경량 확장 |
| 공통 | Timing, minimum bandwidth 보장은 TCP, UDP 모두 제공하지 않음 |
2. Multiplexing과 Demultiplexing

하나의 호스트에서 여러 process가 동시에 네트워크를 사용한다. Transport layer는 이를 관리하기 위해 두 가지 핵심 기능을 수행한다:
- Multiplexing (다중화): 여러 socket의 데이터를 모아서 transport header를 붙이고 network layer에 전달
- Demultiplexing (역다중화): 수신된 segment의 header 정보를 보고 올바른 socket에 전달
Demultiplexing의 핵심은 port 번호다. 각 segment의 header에는 source port와 destination port가 포함되어 있다.
2.1 Connectionless Demultiplexing (UDP)
UDP socket은 (destination IP, destination port) 2-tuple로 식별된다.
- Source IP나 source port가 달라도, destination IP와 port가 같으면 같은 socket으로 전달
- 즉 여러 sender가 보낸 datagram이 하나의 socket으로 모인다
2.2 Connection-oriented Demultiplexing (TCP)
TCP socket은 (source IP, source port, destination IP, destination port) 4-tuple로 식별된다.
- 같은 destination port라도 source IP 또는 source port가 다르면 다른 socket으로 전달
- Web server는 하나의 port(80)에서 수천 개의 동시 TCP 연결을 각각 별도 socket으로 관리
3. UDP (User Datagram Protocol)
UDP [RFC 768]는 “no frills” bare-bones transport protocol이다. IP에 multiplexing/demultiplexing과 간단한 error checking만 추가한 최소한의 프로토콜이다.
특징:
- Best effort: Segment가 손실되거나 순서가 뒤바뀔 수 있다
- Connectionless: Handshaking 없음. 각 segment가 독립적으로 처리됨
3.1 UDP를 사용하는 이유
TCP가 더 많은 기능을 제공하는데 왜 UDP를 쓸까?
- Connection setup 없음: 연결 설정에 드는 RTT 지연이 없다 (DNS가 UDP를 사용하는 이유)
- 연결 상태 없음: Server가 더 많은 client를 수용할 수 있다
- Header가 작다: TCP header 20 bytes vs UDP header 8 bytes
- Congestion control 없음: 원하는 만큼 빠르게 전송할 수 있다. 네트워크 혼잡과 무관하게 일정한 전송 속도 유지 가능
UDP를 사용하는 대표적인 애플리케이션:
- Streaming multimedia (loss tolerant, rate sensitive)
- DNS (빠른 응답이 중요)
- SNMP, HTTP/3 (QUIC)
3.2 UDP Segment 구조

UDP header는 단 8 bytes로 구성된다:
| Field | 크기 | 설명 |
|---|---|---|
| Source Port | 16 bits | 송신 process의 port 번호 |
| Dest Port | 16 bits | 수신 process의 port 번호 |
| Length | 16 bits | Header를 포함한 UDP segment의 전체 길이 (bytes) |
| Checksum | 16 bits | 오류 검출용 |
3.3 UDP Checksum

UDP checksum은 전송 중 발생한 bit error를 검출하는 메커니즘이다.
계산 방법:
- Segment의 내용을 16-bit word 단위로 분할
- 모든 16-bit word를 더한다 (1의 보수 덧셈, carry가 발생하면 wrap around)
- 합의 1의 보수(complement)를 checksum으로 사용
수신 측에서 모든 16-bit word(checksum 포함)를 더하면 결과가 1111111111111111이어야 한다. 아니라면 error가 검출된 것이다.
UDP checksum이 오류를 검출하지 못하는 경우
Checksum은 모든 오류를 검출하지는 못한다. 예를 들어, 두 bit가 동시에 반전되어 합이 우연히 같아지는 경우가 있을 수 있다. 하지만 단일 bit error는 항상 검출할 수 있다.
4. Reliable Data Transfer의 원리
Reliable data transfer(rdt)는 transport layer의 핵심 문제다. 하위 채널(network layer)이 unreliable하더라도, 상위 계층(application)에는 reliable한 데이터 전송을 제공해야 한다.

이 문제를 점진적으로 해결해 나가면서 프로토콜을 발전시켜 보자. FSM(Finite State Machine)을 사용하여 sender와 receiver의 동작을 명세한다.
4.1 rdt 1.0: 완벽한 채널 위의 Reliable Transfer
가정: 하위 채널이 완벽히 reliable (bit error 없음, packet loss 없음)
이 경우 sender와 receiver의 FSM은 매우 단순하다:
- Sender: 상위 계층에서 데이터를 받으면 packet을 만들어 전송
- Receiver: 하위 계층에서 packet을 받으면 데이터를 추출하여 상위 계층에 전달
아무런 오류 처리가 필요 없다.
4.2 rdt 2.0: Bit Error가 있는 채널
가정: 하위 채널에서 bit가 뒤집힐(flip) 수 있다 (하지만 packet loss는 없음)
오류를 처리하기 위해 다음 메커니즘을 도입한다:
- Checksum: 수신된 packet에 bit error가 있는지 검출
- ACK (Acknowledgement): Receiver가 “잘 받았다”고 sender에게 알림
- NAK (Negative Acknowledgement): Receiver가 “오류가 있다”고 sender에게 알림
- Retransmission: NAK을 받으면 sender가 해당 packet을 재전송
이 방식을 Stop-and-wait라 한다: Sender가 하나의 packet을 보내고, ACK 또는 NAK를 받을 때까지 기다린다.
rdt 2.0의 치명적 결함
ACK/NAK 자체가 corrupted되면 어떻게 될까?
- Sender는 receiver가 제대로 받았는지 알 수 없다
- 무조건 재전송하면 duplicate(중복) 문제가 발생한다
4.3 rdt 2.1: Sequence Number로 중복 해결
해결책: 각 packet에 sequence number를 추가한다.
- Sender가 각 packet에 sequence number (0 또는 1)를 붙인다
- ACK/NAK가 corrupted되면 sender는 현재 packet을 재전송
- Receiver는 sequence number를 확인하여 중복 packet을 폐기
- Stop-and-wait이므로 sequence number는 0과 1 두 개면 충분하다
4.4 rdt 2.2: NAK-free Protocol
rdt 2.1과 동일한 기능을 ACK만 사용하여 구현한다.
- NAK를 보내는 대신, receiver가 마지막으로 정상 수신한 packet의 sequence number에 대한 ACK를 전송
- Sender가 duplicate ACK를 받으면 NAK와 동일한 의미로 해석하여 재전송
TCP가 이 방식을 사용한다 (NAK-free).
4.5 rdt 3.0: Error와 Loss가 있는 채널
가정: 하위 채널에서 bit error뿐 아니라 packet 자체가 손실(loss)될 수 있다 (data와 ACK 모두)
해결: Countdown timer를 도입한다.
- Sender가 packet을 보낸 후 timer를 시작
- “합리적인” 시간 내에 ACK가 오지 않으면 timeout - packet을 재전송하고 timer 재시작
- Packet이 단지 지연된 것이라면(loss가 아닌 경우)? Seq number로 중복을 처리하므로 문제 없다

위 그림은 (a) 정상 동작과 (b) packet loss 시나리오를 보여준다.

(c) ACK loss와 (d) premature timeout(ACK가 늦게 도착) 시나리오다. 두 경우 모두 timeout에 의한 재전송과 sequence number에 의한 중복 제거로 정상 동작한다.
4.6 rdt 3.0의 성능 문제

rdt 3.0은 정확하지만 성능이 매우 나쁘다. 1 Gbps 링크, 15 ms propagation delay, 8000 bit packet의 예:
Sender utilization:
0.027%의 utilization! 1 Gbps 링크에서 실질적으로 267 kbps만 사용하는 셈이다. Stop-and-wait 방식에서는 프로토콜이 하부 인프라의 성능을 극도로 제한한다.
4.7 Pipelined Protocol

해결: Pipelining - ACK를 기다리지 않고 여러 packet을 동시에 전송한다.
Pipelining의 요구 사항:
- Sequence number의 범위가 커져야 한다 (0, 1만으로는 부족)
- Sender와/또는 receiver에 buffer가 필요하다
Pipelining을 구현하는 두 가지 대표적 프로토콜이 있다: Go-Back-N과 Selective Repeat.
4.8 Go-Back-N (GBN)

Sender: 최대 개의 unACKed packet을 window 내에서 전송할 수 있다.
- Cumulative ACK: ACK()은 번까지의 모든 packet을 수신했다는 의미
- ACK()을 받으면 window를 부터 시작하도록 이동
- 가장 오래된 in-flight packet에 대한 single timer 사용
- Timeout 시: 해당 packet과 window 내의 모든 후속 packet을 재전송
Receiver: 단순하다.
- In-order로 수신된 packet만 ACK
- Out-of-order packet은 폐기 (buffer하지 않음)
- 가장 높은 in-order sequence number에 대한 ACK를 재전송

예시 (window size ): pkt2가 손실되면, pkt3, 4, 5가 도착해도 receiver는 이를 폐기하고 ack1을 반복 전송한다. pkt2의 timer가 만료되면 sender는 pkt2, 3, 4, 5를 모두 재전송한다.
4.9 Selective Repeat (SR)
GBN의 문제: 하나의 packet이 손실되면 많은 packet을 불필요하게 재전송한다.

Selective Repeat은 이를 개선한다:
Sender:
- 각 unACKed packet에 대해 개별 timer 유지
- Timeout 시 해당 packet만 재전송 (GBN처럼 전부 재전송하지 않음)
- ACK()을 받으면 을 수신 완료로 표시, window base가 이면 window 이동
Receiver:
- 수신된 packet에 대해 개별 ACK 전송
- Out-of-order packet은 buffer에 저장
- In-order로 된 packet은 상위 계층에 전달하고 window 이동

예시: pkt2가 손실되어도 pkt3, 4, 5를 buffer에 저장하고 각각 ACK를 보낸다. pkt2가 재전송되면 buffer에 있던 pkt3, 4, 5와 함께 상위 계층에 in-order로 전달한다.
SR의 Dilemma: Sequence Number 크기

Sequence number의 범위가 충분히 크지 않으면 문제가 발생한다. 위 그림에서 sequence number 0, 1, 2, 3 (base 4)과 window size 3인 경우:
- (a) 정상 시나리오: pkt3이 도착하면 receiver는 새로운 pkt0을 기다림
- (b) ACK 전부 손실 시나리오: timeout 후 재전송된 pkt0이 도착하면, receiver는 이것이 새로운 pkt0인지 재전송된 pkt0인지 구분할 수 없다
해결: Window size sequence number space / 2 이어야 한다.
4.10 GBN vs SR 비교
| 비교 항목 | Go-Back-N | Selective Repeat |
|---|---|---|
| ACK 방식 | Cumulative ACK | Individual ACK |
| Receiver buffer | 불필요 (out-of-order 폐기) | 필요 (out-of-order 저장) |
| Timer | Single timer (oldest) | Per-packet timer |
| Timeout 시 | Window 내 전체 재전송 | 해당 packet만 재전송 |
| Receiver 복잡도 | 단순 | 복잡 |
| 네트워크 효율성 | 낮음 (많은 재전송) | 높음 (최소 재전송) |
5. TCP (Transmission Control Protocol)
5.1 TCP 개요
TCP [RFCs: 793, 1122, 2018, 5681, 7323]의 핵심 특성:
- Point-to-point: 하나의 sender, 하나의 receiver
- Reliable, in-order byte stream: “Message boundary”가 없다
- Full duplex: 같은 연결에서 양방향 데이터 흐름
- MSS (Maximum Segment Size): 하나의 segment에 담을 수 있는 최대 데이터 크기
- Cumulative ACK: GBN과 유사
- Pipelining: Congestion control과 flow control이 window size를 결정
- Connection-oriented: 데이터 교환 전 handshaking
- Flow controlled: Sender가 receiver를 overwhelm하지 않음
5.2 TCP Segment 구조

TCP header는 20 bytes (options 제외)로, UDP보다 훨씬 크다:
| Field | 크기 | 설명 |
|---|---|---|
| Source/Dest Port | 각 16 bits | Process 식별 |
| Sequence Number | 32 bits | Segment 데이터의 첫 번째 byte의 byte-stream 번호 |
| Acknowledgement Number | 32 bits | 상대방에게 다음으로 기대하는 byte의 번호 (cumulative ACK) |
| Head Len | 4 bits | TCP header 길이 (32-bit words 단위) |
| Flags (C, E, U, A, P, R, S, F) | 각 1 bit | C, E: congestion notification. RST, SYN, FIN: connection management. ACK: ACK field 유효 |
| Receive Window | 16 bits | Flow control - receiver가 받을 의향이 있는 byte 수 |
| Checksum | 16 bits | Error detection |
| Options | 가변 | MSS 협상 등 |
Sequence Number와 ACK

- Sequence number: Segment 데이터의 첫 byte에 대한 byte-stream 번호. 예를 들어 MSS가 1000 bytes이고 데이터가 500,000 bytes라면, 첫 segment의 sequence number는 0, 두 번째는 1000, 세 번째는 2000…
- ACK number: 상대방에게 다음으로 기대하는 byte의 번호. ACK=80이면 “79번 byte까지 받았으니 80번부터 보내달라”는 의미
위 telnet 예시: Host A가 Seq=42, ACK=79, data=‘C’를 보내면, Host B는 Seq=79, ACK=43, data=‘C’(echo)로 응답한다.
5.3 TCP RTT 추정과 Timeout
TCP timeout은 RTT보다 길어야 한다. 하지만 RTT는 가변적이다.
- 너무 짧은 timeout: 조기 만료, 불필요한 재전송
- 너무 긴 timeout: Segment loss에 대한 반응이 느림
EstimatedRTT (EWMA)
SampleRTT: Segment 전송부터 ACK 수신까지 측정한 실제 시간. 재전송된 segment는 무시.
- EWMA (Exponential Weighted Moving Average): 과거 sample의 영향이 지수적으로 감소
- 일반적으로

그래프에서 SampleRTT(파란 점)는 변동이 크지만, EstimatedRTT(분홍 선)는 부드럽게 평균을 추적한다.
Timeout 값 결정
여기서 DevRTT는 SampleRTT의 변동폭(safety margin)을 반영한다:
- 일반적으로
- EstimatedRTT의 변동이 클수록 safety margin이 커진다
5.4 TCP Reliable Data Transfer
TCP는 unreliable한 IP service 위에서 reliable data transfer를 제공한다. 핵심 메커니즘:
- Pipelined segment 전송
- Cumulative ACK
- Single retransmission timer (가장 오래된 unACKed segment에 대해)
TCP Sender의 세 가지 Event
- Application으로부터 데이터 수신: Seq number를 붙인 segment 생성, timer가 동작 중이 아니면 시작
- Timeout: Timeout을 유발한 segment를 재전송, timer 재시작
- ACK 수신: 이전에 unACKed였던 segment가 ACK되면 갱신, 아직 unACKed segment가 있으면 timer 재시작
TCP Retransmission 시나리오

- Lost ACK: Host A가 Seq=92를 보내고, Host B의 ACK=100이 손실. Timeout 후 Seq=92 재전송
- Premature timeout: Seq=92와 Seq=100을 보냈는데, timeout이 ACK보다 먼저 발생. Seq=92를 재전송하면, 이미 도착한 ACK=120 (cumulative)이 들어와서 Host A는 120까지 수신 완료로 처리
TCP Fast Retransmit

Timeout을 기다리는 것은 오래 걸릴 수 있다. Triple duplicate ACK를 활용하여 더 빠르게 대응한다:
- Sender가 같은 데이터에 대한 ACK를 3번 중복으로 받으면(원래 ACK + 3 duplicate = 총 4개), 해당 unACKed segment가 손실되었다고 판단
- Timeout을 기다리지 않고 즉시 재전송
3개의 duplicate ACK가 의미하는 것: 손실된 segment 이후의 3개 segment가 수신되었다는 것이다. 네트워크가 완전히 다운된 것이 아니라 특정 segment만 손실된 것이므로, timeout까지 기다릴 필요 없이 빠르게 재전송할 수 있다.
5.5 TCP Flow Control

Flow control은 sender가 receiver의 buffer를 overflow시키지 않도록 전송 속도를 조절하는 메커니즘이다.
Flow Control vs Congestion Control
두 개념을 혼동하기 쉽다:
- Flow control: Receiver가 처리할 수 있는 속도에 맞춤 (1:1 관계)
- Congestion control: 네트워크가 처리할 수 있는 속도에 맞춤 (다수 sender와 네트워크의 관계)
동작 방식:
- TCP receiver는 TCP header의
rwnd(receive window) field를 통해 남은 buffer 공간을 sender에게 알린다 RcvBuffer의 기본 크기는 보통 4096 bytes이며, OS가 자동 조정하기도 한다- Sender는 in-flight 데이터의 양을
rwnd이하로 유지한다:
이를 통해 receiver의 buffer가 넘치지 않음을 보장한다.
5.6 TCP Connection Management
데이터 교환 전에 sender와 receiver는 handshake를 통해 연결을 설정해야 한다.
왜 2-Way Handshake로는 부족한가?
네트워크에는 가변적인 delay, message loss, reordering이 있다. 2-way handshake에서는:
- 재전송된
req_conn(x)가 지연되어 server에 늦게 도착하면, server가 이미 종료된 연결을 다시 ESTAB로 전환하는 half open connection 문제 발생 - 또는 중복 데이터를 수락하는 문제 발생
TCP 3-Way Handshake

- Client → Server:
SYNbit=1, Seq=x(client가 초기 sequence number 선택)- Client 상태: LISTEN → SYN SENT
- Server → Client:
SYNbit=1, Seq=y, ACKbit=1, ACKnum=x+1(server가 초기 sequence number 선택, client의 SYN에 ACK)- Server 상태: LISTEN → SYN RCVD
- Client → Server:
ACKbit=1, ACKnum=y+1(이 segment에 client-to-server 데이터를 포함할 수 있음)- Client 상태: ESTAB, 이후 Server도 ESTAB
3-way handshake가 2-way보다 안전한 이유: 세 번째 ACK를 통해 양쪽 모두 상대방이 살아있고 연결을 수락했음을 확인한다.
TCP 연결 종료
- Client와 server 각각 자신의 방향의 연결을 닫는다
- FIN bit = 1인 TCP segment를 전송하여 종료 의사 표시
- FIN을 받으면 ACK로 응답하고, 자신의 FIN도 전송
- 양쪽의 FIN이 모두 ACK되면 연결 종료
6. Congestion Control의 원리
6.1 Congestion이란?
Congestion은 “너무 많은 source가 너무 많은 데이터를 너무 빨리 보내서 네트워크가 처리할 수 없는 상황”이다.
증상:
- Router buffer에서의 긴 queueing delay
- Router buffer overflow에 의한 packet loss
Flow Control과의 차이
Flow control은 하나의 sender가 하나의 receiver를 위해 속도를 조절하는 것이고, congestion control은 많은 sender가 네트워크 전체를 위해 속도를 조절하는 것이다.
6.2 Congestion의 비용

세 가지 시나리오를 통해 congestion의 비용을 분석한다:
- Throughput은 절대 link capacity를 초과할 수 없다
- Capacity에 가까워지면 delay가 급격히 증가한다
- 재전송(loss/retransmission)으로 인해 effective throughput이 감소한다 - 링크 용량의 일부가 재전송에 낭비됨
- 불필요한 중복 재전송(un-needed duplicates)은 effective throughput을 더욱 감소시킨다
- Multi-hop 경로에서 packet이 downstream에서 drop되면, upstream의 전송 용량이 모두 낭비된다
6.3 Congestion Control 접근법
| 접근법 | 설명 |
|---|---|
| End-to-end | 네트워크로부터 명시적 feedback 없음. Loss와 delay를 관찰하여 congestion을 추론. TCP가 사용하는 방식 |
| Network-assisted | Router가 congestion 정보를 직접 sender에게 피드백. TCP ECN, ATM DECbit 등 |
7. TCP Congestion Control
7.1 AIMD (Additive Increase, Multiplicative Decrease)

TCP congestion control의 기본 원리:
- Additive Increase: Loss가 감지되지 않으면, 매 RTT마다 전송률을 1 MSS씩 선형 증가
- Multiplicative Decrease: Loss가 감지되면, 전송률을 절반으로 감소
이 동작은 시간에 따라 “톱니(sawtooth)” 패턴을 만든다 - 대역폭을 점진적으로 탐색(probing)하다가, congestion을 감지하면 급격히 줄이는 행동을 반복한다.
구체적인 multiplicative decrease:
- Triple duplicate ACK로 loss 감지 시:
cwnd를 절반으로 (TCP Reno) - Timeout으로 loss 감지 시:
cwnd를 1 MSS로 (TCP Tahoe)
7.2 TCP Congestion Control 상세
TCP sender는 cwnd (congestion window)를 관리한다:
Sender는 in-flight 데이터를 cwnd 이하로 유지한다:
cwnd는 네트워크 congestion에 따라 동적으로 조정된다.
Slow Start

연결이 시작되면 cwnd = 1 MSS에서 출발한다:
- 매 ACK 수신 시
cwnd를 1 MSS 증가 (결과적으로 매 RTT마다 2배로 - 지수적 증가) - 이름은 “slow” start이지만 실제 증가는 exponential이다
Slow start가 끝나는 조건:
- Loss가 감지되면 (timeout 또는 triple duplicate ACK)
cwnd가ssthresh(slow start threshold)에 도달하면 congestion avoidance로 전환
Congestion Avoidance
cwnd >= ssthresh이면 congestion avoidance 단계에 진입한다:
- 매 RTT마다
cwnd를 1 MSS씩 선형 증가 (additive increase) - 구현: 각 ACK 수신 시
cwnd = cwnd + MSS * (MSS/cwnd)
Loss 감지 시:
ssthresh = cwnd / 2로 설정- Timeout:
cwnd = 1 MSS, slow start로 복귀 - Triple duplicate ACK:
cwnd = cwnd / 2, fast recovery 단계로 진입 (TCP Reno)
TCP Congestion Control FSM

세 가지 상태를 순환한다:
- Slow Start: 지수적 증가.
cwnd >= ssthresh이면 congestion avoidance로. Loss 시 ssthresh 갱신 후 적절한 상태로. - Congestion Avoidance: 선형 증가. Triple duplicate ACK이면 fast recovery로. Timeout이면 slow start로.
- Fast Recovery (TCP Reno): 진입 시
ssthresh = cwnd/2,cwnd = ssthresh + 3*MSS로 설정. 이후 duplicate ACK마다cwnd += MSS. New ACK가 오면cwnd = ssthresh로 설정하고 congestion avoidance로. Timeout이면 slow start로.
7.3 TCP CUBIC

Classic AIMD의 한계: Loss 후 cwnd가 반으로 줄었다가 다시 선형으로 증가하면, 이전 최대값인 까지 도달하는 데 오래 걸린다.
TCP CUBIC의 아이디어:
- : Congestion loss가 감지된 시점의 sending rate
- Loss 이후 bottleneck의 congestion 상태는 크게 변하지 않았을 것
- 따라서 에서 먼 때는 빠르게 증가하고, 가까워지면 천천히 조심스럽게 증가
구현:
- :
cwnd가 에 도달할 예정 시점 cwnd를 현재 시간과 의 거리의 세제곱(cube)에 비례하여 증가- 에서 멀면 큰 폭으로 증가
- 에 가까우면 작은 폭으로 증가 (cautious)
- 를 넘으면 다시 천천히 증가 (새로운 용량 탐색)
TCP CUBIC은 Linux의 기본 TCP이며, 현재 가장 널리 사용되는 TCP congestion control 알고리즘이다.
7.4 Delay-based Congestion Control
Classic TCP(CUBIC 포함)는 loss를 congestion의 신호로 사용한다. 이는 bottleneck link의 queue를 가득 채우고 packet을 drop시킨 후에야 반응한다는 의미다.
Delay-based 접근: RTT 증가를 congestion의 초기 신호로 사용한다.
- : 관측된 최소 RTT (uncongested 경로의 RTT)
- Uncongested throughput:
- 실측 throughput:
동작:
- 실측 throughput이 uncongested throughput에 가까우면:
cwnd를 선형 증가 (경로가 혼잡하지 않으므로) - 실측 throughput이 uncongested throughput보다 크게 낮으면:
cwnd를 선형 감소 (경로가 혼잡하므로)
목표: “End-to-end pipe를 가득 차게, 하지만 넘치지 않게” 유지.
대표 프로토콜: BBR (Bottleneck Bandwidth and Round-trip propagation time) - Google의 내부 backbone network에 배포됨.
7.5 ECN (Explicit Congestion Notification)
Network-assisted congestion control의 구현:
- IP header의 ToS field에 2 bits (ECN bits)가 router에 의해 marking됨
- Source가 보낸 IP datagram의 ECN=
10→ router가 혼잡 감지 시 ECN=11로 변경 - Destination이 이를 수신하면, ACK segment의 ECE (ECN Echo) bit를 1로 설정하여 source에 congestion을 알림
- IP(Network layer)와 TCP(Transport layer) 모두 관여한다
7.6 TCP Fairness
Fairness goal: 개의 TCP 연결이 대역폭 인 bottleneck link를 공유하면, 각 연결의 평균 전송률이 여야 한다.
TCP AIMD가 fair한가? 이상적 조건 하에서는 그렇다:
- Additive increase는 기울기 1로 throughput을 증가시키고 (equal bandwidth share 방향)
- Multiplicative decrease는 throughput을 비례적으로 감소시킨다 (원점 방향)
- 이 과정을 반복하면 두 연결의 throughput이 equal bandwidth share 선에 수렴한다
단, 이는 다음 조건에서만 성립:
- 모든 연결의 RTT가 같을 때
- 고정된 수의 연결이 congestion avoidance에서만 동작할 때
현실에서의 fairness 한계:
- UDP: Congestion control이 없어 원하는 만큼 전송 가능. “Internet police”가 없으므로 TCP와 불공평
- Parallel TCP: 하나의 application이 여러 TCP 연결을 열면 더 많은 share를 차지 (link rate , 기존 9개 연결에서 새 app이 1 TCP: , 11 TCP: )
8. Transport Layer의 진화: QUIC
TCP와 UDP는 40년 넘게 Internet의 주요 transport protocol이었지만, 새로운 환경에서 한계가 있다:
| 시나리오 | 도전 과제 |
|---|---|
| Long, fat pipes | 많은 in-flight packet. Loss 시 pipeline 중단 |
| Wireless | 무선 링크의 loss를 congestion loss로 오인 |
| Long-delay links | RTT가 매우 긺 |
| Data center | Latency 민감 |
8.1 QUIC (Quick UDP Internet Connections)
QUIC은 transport layer 기능을 application layer에서, UDP 위에 구현한다.
핵심 특성:
- TCP의 error/congestion control 알고리즘을 채택하되, application layer에서 구현
- Connection establishment: Reliability, congestion control, authentication, encryption을 1 RTT 안에 설정 (TCP+TLS는 2번의 serial handshake 필요)
- Multiple streams: 여러 application-level stream을 하나의 QUIC 연결 위에 다중화
- 각 stream별로 독립적인 reliable data transfer
- 공통 congestion control

TCP+TLS는 연결 설정에 2 RTT (TCP handshake + TLS handshake)가 필요하지만, QUIC은 1 RTT만에 연결 설정과 보안을 모두 완료한다.

HTTP/2에서 하나의 TCP 연결 위에 multiple stream을 다중화하는데, TCP 레벨에서 packet loss가 발생하면 해당 TCP 연결의 모든 stream이 stall된다 (HOL blocking). QUIC에서는 각 stream이 독립적인 error recovery를 가지므로, 한 stream의 loss가 다른 stream에 영향을 주지 않는다.
9. Chapter 3 정리
| 주제 | 핵심 내용 |
|---|---|
| Transport Layer | Process 간 논리적 통신. Multiplexing/Demultiplexing (port 기반) |
| UDP | Connectionless, unreliable, 8-byte header. Checksum으로 error detection |
| Reliable Data Transfer | rdt 1.0(완벽한 채널) → 2.0(checksum+ACK/NAK) → 2.1(sequence number) → 2.2(NAK-free) → 3.0(timer) |
| Pipelining | Stop-and-wait의 낮은 utilization 해결. GBN(cumulative ACK) vs SR(individual ACK) |
| TCP | Reliable byte stream, cumulative ACK, single timer. Seq number는 byte 단위 |
| TCP RTT/Timeout | EWMA로 EstimatedRTT 계산. TimeoutInterval = EstimatedRTT + 4*DevRTT |
| TCP Flow Control | rwnd field로 receiver buffer 여유 공간 통보. Sender는 in-flight ⇐ rwnd |
| TCP Connection | 3-way handshake (SYN, SYNACK, ACK). FIN으로 연결 종료 |
| Congestion Control | Flow control과 구분. End-to-end vs Network-assisted |
| TCP AIMD | Additive increase(+1 MSS/RTT), Multiplicative decrease(cwnd/2). Sawtooth 패턴 |
| Slow Start | cwnd=1 MSS에서 시작, 지수적 증가. ssthresh 도달 시 congestion avoidance로 전환 |
| TCP CUBIC | 근처에서 cautious하게 접근. Linux 기본 TCP |
| Delay-based | RTT 증가로 congestion 탐지 (BBR). Loss 발생 전에 대응 |
| QUIC | UDP 위의 application-layer transport. 1 RTT connection setup. Per-stream error recovery |