Infra & Security Eng/Network & Security
rdt 2.1 완벽 정리: Sequence Number를 활용한 ACK/NAK 오류 제어와 Sender-Receiver 메커니즘
by 엔지니어 E
2026. 2. 11.
rdt 2.1(Sender)
송신측은 패킷에 0번과 1번 번호를 번갈아 붙여서 보내며, 상대방의 대답을 확인하고 다음 단계로 넘어간다
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) (만든 패킷을 하위 채널로 전송함)
2단계: 0번 응답 확인 (Wait for ACK or NAK 0)
- 상황 A: 응답이 깨졌거나 NAK인 경우 (실패)
- (4) 이벤트: rdt_rcv(rcvpkt) && (corrupt(rcvpkt) || isNAK(rcvpkt)) (응답을 받았는데 내용이 깨졌거나 NAK가 도착함)
- (5) 액션: udt_send(sndpkt) (이미 보냈던 0번 패킷을 다시 전송함)
* 이미지에서 자기 자신에게로 되돌아가는 둥근 화살표는 상황이 실패했을 때 **"지금 상태를 유지하며 같은 일을 반복한다"**는 뜻
- 상황 B: 응답이 멀쩡하고 ACK인 경우 (성공)
- (6) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt) (응답이 깨지지 않았고 ACK가 도착함)
- (7) 액션: $\Lambda$ (아무런 추가 동작을 하지 않음)
3단계: 1번 패킷 전송 (Wait for call 1 from above)
- (8) 이벤트: rdt_send(data) (상위 애플리케이션으로부터 다음 데이터가 내려옴)
- (9) 액션 1: sndpkt = make_pkt(1, data, checksum) (1번 번호와 데이터, 체크섬을 포함한 패킷을 만듦)
- (10) 액션 2: udt_send(sndpkt) (만든 패킷을 하위 채널로 전송함)
4단계: 1번 응답 확인 (Wait for ACK or NAK 1)
- 상황 A: 응답이 깨졌거나 NAK인 경우 (실패)
- (11) 이벤트: rdt_rcv(rcvpkt) && (corrupt(rcvpkt) || isNAK(rcvpkt)) (응답을 받았는데 내용이 깨졌거나 NAK가 도착함)
- (12) 액션: udt_send(sndpkt) (이미 보냈던 1번 패킷을 다시 전송함)
* 이미지에서 자기 자신에게로 되돌아가는 둥근 화살표는 상황이 실패했을 때 **"지금 상태를 유지하며 같은 일을 반복한다"**는 뜻
- 상황 B: 응답이 멀쩡하고 ACK인 경우 (성공)
- (13) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt) (응답이 깨지지 않았고 ACK가 도착함)
- (14) 액션: $\Lambda$ (아무런 추가 동작을 하지 않음)
|
rdt 2.1(Receiver)
0번 패킷이 올 차례이다. 여기서는 3가지 상황이 발생할 수 있다
1단계: 0번 패킷 기다리기 (Wait for 0 from below)
- 상황 A: 패킷이 깨졌을 때 (Corrupt)
- (1) 이벤트: rdt_rcv(rcvpkt) && (corrupt(rcvpkt))
- (2) 액션 1: sndpkt = make_pkt(NAK, chksum) (못 알아들었으니 NAK 패킷을 만듦)
- (3) 액션 2: udt_send(sndpkt) (NAK 전송)
- 결과: 자기 자신에게 돌아와 다시 0번을 기다림 (제자리 화살표)
- 상황 B: 패킷은 안 깨졌는데 번호가 1번일 때 (중복 패킷)
- (4) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq1(rcvpkt)
- (5) 액션 1: sndpkt = make_pkt(ACK, chksum) (이미 받은 거니 잘 받았다고 ACK는 보내줌)
- (6) 액션 2: udt_send(sndpkt) (ACK 전송)
- 결과: 데이터는 버리고 다시 0번을 기다림 (제자리 화살표)
- 상황 C: 기다리던 0번 패킷이 제대로 왔을 때 (성공)
- (7) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq0(rcvpkt)
- (8) 액션 1: extract(rcvpkt, data) (패킷에서 데이터 추출)
- (9) 액션 2: deliver_data(data) (상위 앱으로 데이터 전달)
- (10) 액션 3: sndpkt = make_pkt(ACK, chksum) (잘 받았다고 ACK 패킷 만듦)
- (11) 액션 4: udt_send(sndpkt) (ACK 전송)
- 결과: 0번 처리가 끝났으므로 1번 패킷을 기다리는 상태로 이동
2단계: 1번 패킷 기다리기 (Wait for 1 from below)
이제 1번 패킷이 올 차례입니다. 1단계와 구조는 같고 번호만 바뀝니다.
- 상황 A: 패킷이 깨졌을 때 (Corrupt)
- (12) 이벤트: rdt_rcv(rcvpkt) && (corrupt(rcvpkt))
- (13) 액션: NAK 패킷을 만들어 전송 (make_pkt, udt_send)
- 상황 B: 패킷은 안 깨졌는데 번호가 0번일 때 (중복 패킷)
- (14) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq0(rcvpkt)
- (15) 액션: ACK 패킷을 만들어 전송 (make_pkt, udt_send)
- 상황 C: 기다리던 1번 패킷이 제대로 왔을 때 (성공)
- (16) 이벤트: rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq1(rcvpkt)
- (17) 액션: 데이터 추출 → 앱 전달 → ACK 패킷 생성 → 전송
- 결과: 다시 0번 패킷을 기다리는 상태로 돌아감
|