본문 바로가기
Infra & Security Eng/Network & Security

rdt 3.0 완벽 정리: 타이머(Timer)를 활용한 패킷 유실 해결과 신뢰적 전송의 완성

by 엔지니어 E 2026. 2. 11.
반응형

[송신측] rdt 3.0: 유실에 대응하는 타이머 메커니즘

rdt 3.0의 핵심은 Countdown Timer이다패킷을 보내고 일정 시간(Timeout) 동안 대답이 없으면 잃어버린 것으로 간주하고 다시 보냅니다.

1단계: 0번 패킷 전송 (Wait for call 0 from above)

  • (1) 이벤트: rdt_send(data) (데이터가 내려옴)
  • (2) 액션 1: sndpkt = make_pkt(0, data, checksum) (0번 패킷 생성)
  • (3) 액션 2: udt_send(sndpkt) (패킷 전송)
  • (4) 액션 3: start_timer (유실을 확인하기 위해 타이머 시작)

2단계: 0번 ACK 확인 대기 (Wait for ACK 0)

이 상태에서는 '유실' 상황을 처리하는 액션이 추가됩니다.
  • 상황 A: 잘못된 응답이 온 경우 (무시)
    • (5) 이벤트: rdt_rcv(rcvpkt) && (corrupt(rcvpkt) || isACK(rcvpkt, 1)) (내용이 깨졌거나 1번 ACK가 온 경우)
    • (6) 액션: $\Lambda$ (아무것도 하지 않고 계속 기다림)
  • 상황 B: 기다려도 응답이 없는 경우 (타임아웃)
    • (7) 이벤트: timeout (합리적인 시간만큼 기다렸으나 대답이 없음)
    • (8) 액션 1: udt_send(sndpkt) (패킷을 다시 전송)
    • (9) 액션 2: start_timer (타이머 다시 시작)
  • 상황 C: 정확한 응답이 온 경우 (성공)
    • (10) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt, 0) (멀쩡한 0번 ACK 도착)
    • (11) 액션: stop_timer (무사히 받았으니 타이머 정지)
    • 결과: 1번 패킷 전송 단계로 이동

3단계: 1번 패킷 전송 (Wait for call 1 from above)

  • (12) 이벤트: rdt_send(data)
  • (13) 액션: 패킷 생성 → 전송 → start_timer

4단계: 1번 ACK 확인 대기 (Wait for ACK 1)

  • 상황 A (잘못된 응답): 깨졌거나 0번 ACK가 오면 무시($\Lambda$)
  • 상황 B (타임아웃): 대답이 없으면 패킷 재전송 후 타이머 다시 시작
  • 상황 C (정상 수신): 멀쩡한 1번 ACK가 오면 stop_timer 후 다시 0번 대기 상태로 복귀

 

수신측

수신측이 **0번 패킷을 기다리는 상태(Wait for 0 from below)**를 기준으로 설명한다 * 수신측은 rdt 2.2와 같은 메커니즘이다

1단계: 패킷 수신 및 상태 확인 (Wait for 0 from below)

수신자는 송신자로부터 패킷이 오기를 기다린다
  • 상황 A: 패킷이 깨졌거나 1번 패킷(이전 패킷)이 온 경우 (실패)
    • (1) 이벤트: rdt_rcv(rcvpkt) && (corrupt(rcvpkt) || has_seq1(rcvpkt))
      • 패킷이 오는 도중 망가졌거나(corrupt), 내가 기다리는 0번이 아니라 이미 받았던 1번 패킷이 다시 온 상황이다
    • (2) 액션: udt_send(sndpkt)
      • 새로운 ACK를 만들지 않고, **가장 최근에 성공했던 1번 패킷에 대한 ACK(ACK 1)**를 다시 보낸다
    • 결과: 0번을 계속 기다려야 하므로 자기 자신의 상태로 돌아온다
  • 상황 B: 0번 패킷이 제대로 온 경우 (성공)
    • (3) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq0(rcvpkt)
      • 패킷이 깨지지 않았고(notcorrupt), 기다리던 0번 패킷이 정확히 도착함
    • (4) 액션 1: extract(rcvpkt, data)
      • 패킷에서 실제 데이터를 추출함
    • (5) 액션 2: deliver_data(data)
      • 추출한 데이터를 상위 계층(앱)으로 전달함
    • (6) 액션 3: sndpkt = make_pkt(ACK0, chksum)
      • "0번을 잘 받았다"는 의미로 ACK 0 패킷을 새로 만듦
    • (7) 액션 4: udt_send(sndpkt)
      • 완성된 ACK 0 패킷을 송신자에게 보냅
결과: 0번 처리가 끝났으므로 다음 상태(1번 패킷을 기다리는 상태)로 넘어감

2단계: 1번 패킷 기다리기 (Wait for 1 from below)

0번 패킷 처리를 무사히 마치고, 이제 1번 패킷이 오기를 기다리는 상태
  • 상황 A: 패킷이 깨졌거나 0번 패킷(이전 패킷)이 온 경우 (실패)
    • (8) 이벤트: rdt_rcv(rcvpkt) && (corrupt(rcvpkt) || has_seq0(rcvpkt))
    • 내용: 패킷이 훼손되었거나, 이미 처리한 0번 패킷이 다시 온 상황
    • (9) 액션: udt_send(sndpkt) (가장 최근에 성공했던 ACK 0를 다시 보냄)
    • 결과: 1번을 계속 기다려야 하므로 자기 자신의 상태로 돌아옴
  • 상황 B: 1번 패킷이 제대로 온 경우 (성공)
    • (10) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq1(rcvpkt)
    • 내용: 기다리던 1번 패킷이 깨지지 않고 정확히 도착함
    • (11) 액션: 데이터 추출 → 앱으로 전달 → ACK 1 패킷 생성 → 송신자에게 전송
    • 결과: 1번 처리가 끝났으므로 다시 처음 상태(0번 패킷 대기)로 돌아감