[심화] 신뢰적 데이터 전송(rdt) 프로토콜의 완벽 분석
네트워크 계층(IP)은 데이터를 목적지까지 배달해주지만, 데이터가 깨지거나(Bit Error), 잃어버리는(Loss) 것을 막아주지는 않음
-> 따라서 전송 계층(TCP)은 신뢰할 수 없는 채널 위에서 신뢰성을 보장하기 위해 rdt(Reliable Data Transfer) 프로토콜 사용
1. rdt 1.0: 완벽한 채널에서의 데이터 전송
1.1 가정 (Assumptions)
- 우리가 사용하는 하부 채널(Underlying Channel) 완벽
- 데이터 전송 도중 비트 오류(Bit Error) 발생 X
- 패킷이 도중에 사라지는 패킷 손실(Packet Loss) 발생 X
1.2 동작 원리
가장 단순한 형태로 별도의 제어 메커니즘이 전혀 필요 없음
- 송신자(Sender): 상위 계층에서 데이터를 받으면 패킷을 만들어 채널로 전송
- 수신자(Receiver): 채널에서 패킷을 받아 데이터를 추출하여 상위 계층으로 올림
- 특징: 흐름 제어(Flow Control)나 에러 제어가 필요 없는 상태
2. rdt 2.0: 비트 오류가 있는 채널 (Stop-and-Wait)
2.1 가정 및 문제점
- 상황: 패킷이 전송되는 동안 물리적인 이유(신호 감쇠, 노이즈 등)로 비트가 0에서 1로 바뀌는 비트 오류(Bit Error) 발생 가능
- 문제: 수신자는 자신이 받은 데이터가 송신자가 보낸 원본인지, 깨진 쓰레기 값인지 알 수 없음
2.2 해결책 (핵심 메커니즘 3가지)
- 오류 검출 (Error Detection): 패킷 헤더에 체크섬(Checksum) 필드 추가 -> 수신자는 이를 통해 데이터 손상 여부를 확인
- 수신자 피드백 (Receiver Feedback):
- ACK (Acknowledgement): "잘 받았음." (오류 없음)
- NAK (Negative Acknowledgement): "오류 발생함. 다시 보내줘." (오류 있음)
- 재전송 (Retransmission): 송신자는 NAK를 받으면 해당 패킷 재전송
2.3 동작 과정 (FSM)
- 송신자: 패킷을 보내고 멈춰서(Stop) 수신자의 응답을 기다립니다(Wait).
- NAK 수신 시: 방금 보낸 패킷을 재전송하고 다시 대기
- ACK 수신 시: 다음 데이터를 보낼 준비
2.4 rdt 2.0의 치명적 결함
- "만약 ACK나 NAK 패킷 자체가 깨져서 오면 어떡하는가?"
- 송신자는 수신자가 "잘 받았다(ACK)"는 건지 "다시 보내라(NAK)"는 건지 알 수 없음
- 만약 송신자가 안전하게 무조건 재전송을 해버린다면? → 수신자는 똑같은 데이터를 두 번 받게 되는(중복 패킷) 문제 발생
3. rdt 2.1: ACK/NAK 손상 해결 (순서 번호의 도입)
3.1 해결책: 순서 번호 (Sequence Number)
- 송신자는 패킷 헤더에 순서 번호(0 또는 1)를 붙여서 전송
- 왜 0과 1만 쓰는가?
- 한 번에 하나씩 보내고 확인받는 방식(Stop-and-Wait)이므로, "방금 보낸 패킷(0)"과 "새로 보낸 패킷(1)"만 구분하면 충분하기 때문입니다.
3.2 상세 동작 과정
- 송신자:
- 데이터에 순서 번호 0을 붙여 전송
- 만약 응답(ACK/NAK)이 깨져서 오면? → "못 알아들었으니 다시 보낸다"하고 0번 패킷 재전송
- 정상적인 ACK가 오면? → 순서 번호 1을 붙여 다음 패킷 전송
- 수신자:
- 0번 패킷을 기다리고 있는데 0번이 왔다? → 정상 처리하고 ACK 전송
- 0번 패킷을 기다리고 있는데 0번이 또 왔다? (중복) → "아, 아까 보낸 ACK가 깨져서 또 보냈구나." 판단하고 데이터는 버리고 ACK만 재전송
- 패킷이 깨졌으면? → NAK 전송
3.3 특징
- 송신자는 자신이 현재 0번을 보내는 상태인지, 1번을 보내는 상태인지 기억해야 하므로 상태(State)의 수가 2배로 늘어남
4. rdt 2.2: NAK 없애기 (NAK-free Protocol)
4.1 동기
- "굳이 NAK라는 별도의 패킷을 만들어야 할까? ACK 하나로 다 처리할 수 없을까?"
4.2 해결책: 중복 ACK (Duplicate ACK)
- 수신자는 무조건 ACK만 전송
- 대신, ACK 패킷에 "내가 마지막으로 완벽하게 받은 패킷의 번호"를 적어서 전송
4.3 동작 예시
- 송신자가 1번 패킷 전송
- 수신자가 받아보니 깨져 있음 (원래라면 NAK를 보내야 함)
- 대신 수신자는 ACK 0 전송 ("나 0번까지는 잘 받았어"라는 뜻)
- 송신자는 1번을 보냈는데 ACK 0이 온 것을 보고, "아, 1번이 잘못됐다는 뜻이구나(NAK와 동일)"라고 해석하여 1번 재전송
5. rdt 3.0: 패킷 손실이 발생하는 채널 (Timer)
5.1 가정 및 문제점
- 상황: 네트워크 혼잡 등으로 인해 패킷이 전송 도중 아예 사라져 버리는(Loss) 현상 발생
- 문제:
- 데이터가 사라지면 수신자는 받은 게 없으니 응답 X
- ACK가 사라지면 송신자는 응답을 받지 못함
- 결국 송신자는 하염없이 응답을 기다리는 교착 상태(Deadlock)에 빠짐
5.2 해결책: 카운트다운 타이머 (Countdown Timer)
송신자는 패킷을 보낸 후, "이 정도면 갔다 왔겠지" 하는 시간만큼만 기다려보고, 그래도 답이 없으면 재전송
5.3 상세 동작 시나리오
- 정상 흐름 (No Loss):
- 패킷 0 전송 → 타이머 시작 → ACK 0 도착 → 타이머 멈춤 → 다음 패킷 전송
- 패킷 손실 (Packet Loss):
- 패킷 0 전송 → 타이머 시작 → (패킷이 사라짐) → 타임아웃(Timeout) 발생 → 패킷 0 재전송 → 타이머 다시 시작
- ACK 손실 (ACK Loss):
- 패킷 0 전송 → 수신자 수신 후 ACK 0 전송 → (ACK가 사라짐) → 타임아웃 발생 → 패킷 0 재전송(중복 전송)
- 수신자는 이미 받은 0번이 또 왔으므로, **중복임을 인지(rdt 2.1의 기능)**하고 데이터는 버린 뒤 ACK 0 재전송
- 조기 타임아웃 (Premature Timeout):
- 패킷이 너무 늦게 가서, ACK가 오기 전에 타이머가 터져서 재전송
- 결국 수신자는 중복 패킷을 받게 되지만, 순서 번호 덕분에 중복 처리가 가능하여 문제없음